feat: Implementa duas conexões Oracle simultâneas
- Oracle LOCAL (Docker): Para salvar TB_RANKING_CONSULTOR - Oracle REMOTO (CAPES): Para ler SUCUPIRA_PAINEL.VM_COORDENADOR - ConsultorRepositoryImpl usa oracle_remote para buscar PPG - RankingRepository usa oracle_local para salvar ranking - ProcessarRankingJob recebe ambos os clientes - Componente B agora está preparado para funcionar Nota: Elasticsearch precisa ser acessível da rede CAPES
This commit is contained in:
20
backend/sql/schema_ppg.sql
Normal file
20
backend/sql/schema_ppg.sql
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
-- Schema para Coordenações de Programa (PPG)
|
||||||
|
-- Dados extraídos de SUCUPIRA_PAINEL via MCP
|
||||||
|
|
||||||
|
CREATE TABLE TB_COORDENACAO_PROGRAMA (
|
||||||
|
ID_PESSOA NUMBER(10) NOT NULL,
|
||||||
|
ID_PROGRAMA_SNPG NUMBER(10) NOT NULL,
|
||||||
|
NM_PROGRAMA VARCHAR2(500),
|
||||||
|
CD_PROGRAMA_PPG VARCHAR2(50),
|
||||||
|
NOTA_PPG VARCHAR2(10),
|
||||||
|
NM_PROGRAMA_MODALIDADE VARCHAR2(100),
|
||||||
|
NM_AREA_AVALIACAO VARCHAR2(200),
|
||||||
|
DT_INICIO_VIGENCIA DATE,
|
||||||
|
DT_FIM_VIGENCIA DATE,
|
||||||
|
DH_CARGA TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
CONSTRAINT PK_COORDENACAO_PROGRAMA PRIMARY KEY (ID_PESSOA, ID_PROGRAMA_SNPG, DT_INICIO_VIGENCIA)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE INDEX IDX_COORD_PPG_PESSOA ON TB_COORDENACAO_PROGRAMA(ID_PESSOA);
|
||||||
|
CREATE INDEX IDX_COORD_PPG_PROGRAMA ON TB_COORDENACAO_PROGRAMA(ID_PROGRAMA_SNPG);
|
||||||
|
CREATE INDEX IDX_COORD_PPG_ATIVO ON TB_COORDENACAO_PROGRAMA(DT_FIM_VIGENCIA);
|
||||||
@@ -14,13 +14,15 @@ class ProcessarRankingJob:
|
|||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
es_client: ElasticsearchClient,
|
es_client: ElasticsearchClient,
|
||||||
oracle_client: OracleClient,
|
oracle_remote_client: OracleClient,
|
||||||
|
oracle_local_client: OracleClient,
|
||||||
ranking_repo: RankingOracleRepository,
|
ranking_repo: RankingOracleRepository,
|
||||||
):
|
):
|
||||||
self.es_client = es_client
|
self.es_client = es_client
|
||||||
self.oracle_client = oracle_client
|
self.oracle_remote_client = oracle_remote_client
|
||||||
|
self.oracle_local_client = oracle_local_client
|
||||||
self.ranking_repo = ranking_repo
|
self.ranking_repo = ranking_repo
|
||||||
self.consultor_repo = ConsultorRepositoryImpl(es_client, oracle_client)
|
self.consultor_repo = ConsultorRepositoryImpl(es_client, oracle_remote_client)
|
||||||
self.calculador = CalculadorPontuacao()
|
self.calculador = CalculadorPontuacao()
|
||||||
|
|
||||||
async def executar(self, limpar_antes: bool = True) -> Dict[str, Any]:
|
async def executar(self, limpar_antes: bool = True) -> Dict[str, Any]:
|
||||||
|
|||||||
@@ -4,17 +4,27 @@ from contextlib import asynccontextmanager
|
|||||||
|
|
||||||
from .routes import router
|
from .routes import router
|
||||||
from .config import settings
|
from .config import settings
|
||||||
from .dependencies import es_client, oracle_client, get_processar_job
|
from .dependencies import es_client, oracle_local_client, oracle_remote_client, get_processar_job
|
||||||
from ...application.jobs.scheduler import RankingScheduler
|
from ...application.jobs.scheduler import RankingScheduler
|
||||||
|
|
||||||
|
|
||||||
@asynccontextmanager
|
@asynccontextmanager
|
||||||
async def lifespan(app: FastAPI):
|
async def lifespan(app: FastAPI):
|
||||||
await es_client.connect()
|
await es_client.connect()
|
||||||
|
|
||||||
|
# Conectar Oracle LOCAL (Docker)
|
||||||
try:
|
try:
|
||||||
oracle_client.connect()
|
oracle_local_client.connect()
|
||||||
|
print("Oracle LOCAL conectado (Docker)")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"AVISO: Oracle não conectou: {e}. Sistema rodando sem Coordenação PPG.")
|
print(f"AVISO: Oracle LOCAL não conectou: {e}")
|
||||||
|
|
||||||
|
# Conectar Oracle REMOTO (CAPES)
|
||||||
|
try:
|
||||||
|
oracle_remote_client.connect()
|
||||||
|
print("Oracle REMOTO conectado (CAPES/SUCUPIRA_PAINEL)")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"AVISO: Oracle REMOTO não conectou: {e}. Sistema rodando sem Componente B (PPG).")
|
||||||
|
|
||||||
scheduler = None
|
scheduler = None
|
||||||
try:
|
try:
|
||||||
@@ -33,8 +43,14 @@ async def lifespan(app: FastAPI):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
await es_client.close()
|
await es_client.close()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
oracle_client.close()
|
oracle_local_client.close()
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
try:
|
||||||
|
oracle_remote_client.close()
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|||||||
@@ -11,9 +11,15 @@ class Settings(BaseSettings):
|
|||||||
ES_USER: str = ""
|
ES_USER: str = ""
|
||||||
ES_PASSWORD: str = ""
|
ES_PASSWORD: str = ""
|
||||||
|
|
||||||
ORACLE_USER: str
|
# Oracle LOCAL (Docker) - Para salvar ranking
|
||||||
ORACLE_PASSWORD: str
|
ORACLE_LOCAL_USER: str
|
||||||
ORACLE_DSN: str
|
ORACLE_LOCAL_PASSWORD: str
|
||||||
|
ORACLE_LOCAL_DSN: str
|
||||||
|
|
||||||
|
# Oracle REMOTO (CAPES) - Para ler SUCUPIRA_PAINEL
|
||||||
|
ORACLE_REMOTE_USER: str
|
||||||
|
ORACLE_REMOTE_PASSWORD: str
|
||||||
|
ORACLE_REMOTE_DSN: str
|
||||||
|
|
||||||
API_HOST: str = "0.0.0.0"
|
API_HOST: str = "0.0.0.0"
|
||||||
API_PORT: int = 8000
|
API_PORT: int = 8000
|
||||||
|
|||||||
@@ -13,8 +13,18 @@ es_client = ElasticsearchClient(
|
|||||||
password=settings.ES_PASSWORD
|
password=settings.ES_PASSWORD
|
||||||
)
|
)
|
||||||
|
|
||||||
oracle_client = OracleClient(
|
# Oracle LOCAL (Docker) - Para salvar ranking
|
||||||
user=settings.ORACLE_USER, password=settings.ORACLE_PASSWORD, dsn=settings.ORACLE_DSN
|
oracle_local_client = OracleClient(
|
||||||
|
user=settings.ORACLE_LOCAL_USER,
|
||||||
|
password=settings.ORACLE_LOCAL_PASSWORD,
|
||||||
|
dsn=settings.ORACLE_LOCAL_DSN
|
||||||
|
)
|
||||||
|
|
||||||
|
# Oracle REMOTO (CAPES) - Para ler SUCUPIRA_PAINEL
|
||||||
|
oracle_remote_client = OracleClient(
|
||||||
|
user=settings.ORACLE_REMOTE_USER,
|
||||||
|
password=settings.ORACLE_REMOTE_PASSWORD,
|
||||||
|
dsn=settings.ORACLE_REMOTE_DSN
|
||||||
)
|
)
|
||||||
|
|
||||||
_repository: ConsultorRepositoryImpl = None
|
_repository: ConsultorRepositoryImpl = None
|
||||||
@@ -25,14 +35,14 @@ _processar_job: ProcessarRankingJob = None
|
|||||||
def get_repository() -> ConsultorRepositoryImpl:
|
def get_repository() -> ConsultorRepositoryImpl:
|
||||||
global _repository
|
global _repository
|
||||||
if _repository is None:
|
if _repository is None:
|
||||||
_repository = ConsultorRepositoryImpl(es_client=es_client, oracle_client=oracle_client)
|
_repository = ConsultorRepositoryImpl(es_client=es_client, oracle_client=oracle_remote_client)
|
||||||
return _repository
|
return _repository
|
||||||
|
|
||||||
|
|
||||||
def get_ranking_repository() -> RankingOracleRepository:
|
def get_ranking_repository() -> RankingOracleRepository:
|
||||||
global _ranking_repository
|
global _ranking_repository
|
||||||
if _ranking_repository is None:
|
if _ranking_repository is None:
|
||||||
_ranking_repository = RankingOracleRepository(oracle_client=oracle_client)
|
_ranking_repository = RankingOracleRepository(oracle_client=oracle_local_client)
|
||||||
return _ranking_repository
|
return _ranking_repository
|
||||||
|
|
||||||
|
|
||||||
@@ -41,7 +51,8 @@ def get_processar_job() -> ProcessarRankingJob:
|
|||||||
if _processar_job is None:
|
if _processar_job is None:
|
||||||
_processar_job = ProcessarRankingJob(
|
_processar_job = ProcessarRankingJob(
|
||||||
es_client=es_client,
|
es_client=es_client,
|
||||||
oracle_client=oracle_client,
|
oracle_remote_client=oracle_remote_client,
|
||||||
|
oracle_local_client=oracle_local_client,
|
||||||
ranking_repo=get_ranking_repository()
|
ranking_repo=get_ranking_repository()
|
||||||
)
|
)
|
||||||
return _processar_job
|
return _processar_job
|
||||||
|
|||||||
Reference in New Issue
Block a user