fix(): Ajuste na função que efetua auditoria no banco de dados

This commit is contained in:
Kenio 2025-11-15 13:13:04 -03:00
parent 42460f4346
commit 78fdb706eb

View file

@ -9,20 +9,37 @@ from packages.v1.administrativo.schemas.log_schema import LogClientIdSchema
from packages.v1.administrativo.actions.log.log_show_database_action import ShowDatabaseAction
# Função auxiliar para comparação de campos
# --- FUNÇÃO AUXILIAR PARA COMPARAÇÃO DE CAMPOS (Fornecida e Mantida) ---
def compare_fields(standard_fields: List[Dict], client_fields: List[Dict], table_name: str) -> List[Dict]:
"""
Compara os campos de uma tabela entre as estruturas padrão e cliente.
"""
discrepancies = []
# 1. Mapear campos do cliente por nome para fácil lookup
# Mapear campos do cliente por nome para fácil lookup
# Esta linha pode causar KeyError: 'FIELD_NAME' se os dados forem malformados.
# Assumimos que a lista de campos é mais confiável do que a lista de tabelas.
try:
client_fields_map = {field['FIELD_NAME']: field for field in client_fields}
except KeyError as e:
# Se ocorrer um erro aqui, a lista de campos está malformada.
# Reportamos isso como uma discrepância na tabela.
return [{
"tabela": table_name,
"tipo": "Erro de Estrutura Interna",
"detalhe": f"Um ou mais campos na tabela do cliente não possuem a chave {e}.",
"padrao": None,
"cliente": client_fields
}]
# 2. Iterar sobre os campos padrão e verificar se existem no cliente
for standard_field in standard_fields:
field_name = standard_field.get('FIELD_NAME')
if not field_name: # Verificação de segurança adicional
continue
if field_name not in client_fields_map:
# Campo que existe no padrão mas não no cliente
discrepancies.append({
@ -44,8 +61,7 @@ def compare_fields(standard_fields: List[Dict], client_fields: List[Dict], table
standard_value = standard_field.get(attr)
client_value = client_field.get(attr)
# Nota: A comparação de strings JSON é mais simples,
# mas requer normalização (ex: null vs NULL, aspas, etc.).
# Nota: Normalize strings/tipos, se necessário, antes desta comparação final
if standard_value != client_value:
discrepancies.append({
"tabela": table_name,
@ -58,16 +74,22 @@ def compare_fields(standard_fields: List[Dict], client_fields: List[Dict], table
return discrepancies
# --- FUNÇÃO PRINCIPAL DE COMPARAÇÃO DE ESTRUTURAS (AJUSTADA) ---
def compare_structures(standard_structure: Dict[str, Any], client_structure: Dict[str, Any]) -> Dict[str, Any]:
"""
Compara a estrutura do cliente com a estrutura padrão e lista as discrepâncias.
Ajuste aplicado: Mapeamento seguro das tabelas do cliente para evitar KeyError
se algum item na lista 'tables' estiver sem a chave 'TABLE_NAME'.
"""
audit_log = {
"discrepancias_encontradas": False,
"detalhes": {
"tabelas_faltando": [],
"elementos_faltando": [], # Para PKs, FKs, Views, etc.
"divergencia_de_campos": [] # Para divergências dentro das tabelas
"elementos_faltando": [],
"divergencia_de_campos": [],
"estrutura_malformada_cliente": None # Novo campo para registrar erros de TABLE_NAME
}
}
@ -76,27 +98,47 @@ def compare_structures(standard_structure: Dict[str, Any], client_structure: Dic
audit_log["discrepancias_encontradas"] = True
return audit_log
# Mapear tabelas padrão e cliente por nome
# 1.1 Mapear tabelas padrão (Assumindo que o JSON padrão é sempre correto)
standard_tables_map = {t['TABLE_NAME']: t for t in standard_structure.get('tables', [])}
client_tables_map = {t['TABLE_NAME']: t for t in client_structure.get('tables', [])}
# 1.2 Mapear tabelas cliente (COM TRATAMENTO DE ERRO: correção para 'KeyError: TABLE_NAME')
client_tables_map = {}
malformed_tables_data = []
for t in client_structure.get('tables', []):
table_name = t.get('TABLE_NAME') # Acesso seguro com .get()
if table_name:
client_tables_map[table_name] = t
else:
# Captura objetos que não têm a chave TABLE_NAME para log
malformed_tables_data.append(t)
# 1.3 Se houve dados malformados, registre na auditoria
if malformed_tables_data:
audit_log["discrepancias_encontradas"] = True
audit_log["detalhes"]["estrutura_malformada_cliente"] = {
"descricao": "Alguns objetos na lista 'tables' do cliente não possuem a chave 'TABLE_NAME' e foram ignorados.",
"objetos_problematicos": malformed_tables_data
}
# --- 1. AUDITORIA DE TABELAS E SEUS CAMPOS ---
# 1.1 Tabelas Faltando (No padrão, mas não no cliente)
# 1.4 Tabelas Faltando (No padrão, mas não no cliente)
missing_tables = standard_tables_map.keys() - client_tables_map.keys()
if missing_tables:
audit_log["discrepancias_encontradas"] = True
audit_log["detalhes"]["tabelas_faltando"].extend(sorted(list(missing_tables)))
# 1.2 Tabelas Correspondentes (Verificação de Campos)
# 1.5 Tabelas Correspondentes (Verificação de Campos)
for table_name, standard_table in standard_tables_map.items():
if table_name in client_tables_map:
client_table = client_tables_map[table_name]
# Assume que os campos são listados sob a chave 'FIELDS'
standard_fields = standard_table.get('FIELDS', [])
client_fields = client_table.get('FIELDS', [])
# Chama a função compare_fields
field_discrepancies = compare_fields(standard_fields, client_fields, table_name)
if field_discrepancies:
@ -111,12 +153,15 @@ def compare_structures(standard_structure: Dict[str, Any], client_structure: Dic
standard_elements = standard_structure.get(element_key, [])
client_elements = client_structure.get(element_key, [])
# Simplifica a comparação para ver se o cliente tem TODOS os elementos do padrão.
# Isto é uma simplificação. O ideal seria mapear por chave composta (ex: TABLE_NAME + INDEX_NAME)
# Convertemos em strings JSON para facilitar a comparação em uma lista/set
# Converte em strings JSON para comparação em conjunto (Set)
try:
standard_set = {json.dumps(item, sort_keys=True) for item in standard_elements}
client_set = {json.dumps(item, sort_keys=True) for item in client_elements}
except TypeError as e:
# Caso algum elemento na lista não seja serializável (ex: None ou tipo misto)
audit_log["discrepancias_encontradas"] = True
audit_log["detalhes"]["erro_serializacao"] = f"Erro ao comparar {element_key}: {e}. Os dados podem estar malformados."
continue
# Encontra elementos que estão no padrão mas não no cliente
missing_elements = standard_set - client_set
@ -128,7 +173,7 @@ def compare_structures(standard_structure: Dict[str, Any], client_structure: Dic
audit_log["detalhes"]["elementos_faltando"].append({
"tipo": element_key,
"detalhe": "Elemento ausente",
"json_padrao": json.loads(missing_str) # Retorna o JSON de volta
"json_padrao": json.loads(missing_str)
})
return audit_log