portal_publico/portal_api/empresas_questor.py

71 lines
3.1 KiB
Python

"""Resolve e cacheia localmente o nome de uma empresa cadastrada no Questor
(banco externo, fora do Django ORM — ver `database/` na raiz do projeto) —
usado por "Cadastro de Regras" (Importação de Plano de Saúde) pra mostrar
"<código> - <nome>" em vez de só o código. Ver `EmpresaQuestor` em
models.py e `sqls/questor.py` pra consulta em si.
`DatabaseConnection` espera a chave em minúsculas ("questor", não
"QUESTOR") — `database.settings.DatabaseSettings` guarda as chaves de
`DATABASE__<nome>__*` do `.env` já normalizadas em minúsculo.
"""
import logging
from database.connection import DatabaseConnection
from sqls.questor import QuestorSQL
from .models import EmpresaQuestor
logger = logging.getLogger(__name__)
def normalizar_codigo_empresa(valor: str) -> str:
"""Remove zeros à esquerda de um código de empresa (ex.: "092" -> "92")
— o Questor guarda `codigoempresa` como número (`smallint`), então "092"
e "92" já eram a mesma empresa lá (a comparação SQL já ignora o zero à
esquerda); esta função garante que o Portal também trate os dois como
um único código canônico, evitando duas regras "diferentes" pra mesma
empresa por causa de zero à esquerda ter sido digitado ou não. Usada em
todo lugar que recebe um `codigo_empresa` de fora (formulário de "+
Nova regra", conferência da planilha anexada) — nunca aplicada a
`ImportacaoPlanoSaudeLinha.codigo_empresa` em si, que precisa
permanecer exatamente como veio da planilha (só normalizada no momento
da comparação). Não numérico (não deveria acontecer) volta só com
espaços removidos, sem alteração."""
valor = (valor or "").strip()
return str(int(valor)) if valor.isdigit() else valor
def resolve_nome_empresa(codigo_empresa: str) -> str | None:
"""Devolve o nome da empresa pro código informado — primeiro olha o
cache local (`EmpresaQuestor`); só consulta o Questor de fato na
primeira vez que um código aparece, e persiste o resultado pra nunca
precisar repetir a consulta depois (ver docstring de `EmpresaQuestor`).
Devolve `None` se o código não existir no Questor ou se o banco estiver
inacessível — nunca propaga a exceção, já que isso é usado só pra
exibição (nunca bloqueia cadastrar/editar uma regra)."""
codigo_empresa = normalizar_codigo_empresa(codigo_empresa)
if not codigo_empresa:
return None
cache = EmpresaQuestor.objects.filter(codigo_empresa=codigo_empresa).first()
if cache:
return cache.nome_empresa
try:
with DatabaseConnection("questor") as db:
linha = db.select_mappings_query(QuestorSQL.consulta_nome_empresa(codigo_empresa), one=True)
except Exception:
logger.exception("Falha ao consultar nome da empresa %s no Questor", codigo_empresa)
return None
if not linha:
return None
nome_empresa = (linha["nomeempresa"] or "").strip()
if not nome_empresa:
return None
EmpresaQuestor.objects.update_or_create(
codigo_empresa=codigo_empresa, defaults={"nome_empresa": nome_empresa}
)
return nome_empresa