diff --git a/packages/v1/administrativo/services/log/log_show_database_service.py b/packages/v1/administrativo/services/log/log_show_database_service.py index 57adc1d..677fb52 100644 --- a/packages/v1/administrativo/services/log/log_show_database_service.py +++ b/packages/v1/administrativo/services/log/log_show_database_service.py @@ -13,13 +13,15 @@ def is_ignored(name: str) -> bool: """Verifica se o nome contém a substring de filtro (case-insensitive).""" if name is None: return False - # Garante que a comparação é feita em caixa alta para robustez return FILTER_SUBSTRING in str(name).upper() -# --- FUNÇÃO HELPER PARA NORMALIZAÇÃO (REMOÇÃO DE SOURCE_CODE) --- +# --- FUNÇÃO HELPER PARA REMOÇÃO DE SOURCE_CODE --- -def normalize_element_for_comparison(item: Dict) -> Dict: - """Remove SOURCE_CODE para comparação e debug, usando uma cópia para proteger o original.""" +def _remove_source_code(item: Dict) -> Dict: + """ + Remove o campo 'SOURCE_CODE' de um item de dicionário. + Usado para garantir que o código-fonte nunca seja retornado/comparado. + """ item_copy = item.copy() if 'SOURCE_CODE' in item_copy: del item_copy['SOURCE_CODE'] @@ -73,7 +75,7 @@ def compare_fields(standard_fields: List[Dict], client_fields: List[Dict], table return discrepancies -# --- FUNÇÃO PRINCIPAL DE COMPARAÇÃO DE ESTRUTURAS (AJUSTADA: Ignorando SOURCE_CODE em LOGS) --- +# --- FUNÇÃO PRINCIPAL DE COMPARAÇÃO DE ESTRUTURAS --- def compare_structures(standard_structure: Dict[str, Any], client_structure: Dict[str, Any]) -> Dict[str, Any]: @@ -117,7 +119,7 @@ def compare_structures(standard_structure: Dict[str, Any], client_structure: Dic if is_ignored(table_name): audit_log["elementos_ignorados"]["tabelas_padrao"].append({ "identificador": table_name, - "estrutura_completa": normalize_element_for_comparison(t) # Removendo SOURCE_CODE + "estrutura_completa": _remove_source_code(t) # Limpeza de SOURCE_CODE }) elif table_name: standard_tables_filtered.append(t) @@ -133,7 +135,7 @@ def compare_structures(standard_structure: Dict[str, Any], client_structure: Dic if is_ignored(table_name): audit_log["elementos_ignorados"]["tabelas_cliente"].append({ "identificador": table_name, - "estrutura_completa": normalize_element_for_comparison(t) # Removendo SOURCE_CODE + "estrutura_completa": _remove_source_code(t) # Limpeza de SOURCE_CODE }) elif table_name: client_tables_map[table_name] = t @@ -183,7 +185,7 @@ def compare_structures(standard_structure: Dict[str, Any], client_structure: Dic "origem": "padrao", "tipo": element_key, "identificador": identifier, - "estrutura_completa": normalize_element_for_comparison(item) # Removendo SOURCE_CODE + "estrutura_completa": _remove_source_code(item) # Limpeza de SOURCE_CODE }) else: standard_elements_filtered.append(item) @@ -196,14 +198,15 @@ def compare_structures(standard_structure: Dict[str, Any], client_structure: Dic "origem": "cliente", "tipo": element_key, "identificador": identifier, - "estrutura_completa": normalize_element_for_comparison(item) # Removendo SOURCE_CODE + "estrutura_completa": _remove_source_code(item) # Limpeza de SOURCE_CODE }) else: client_elements_filtered.append(item) # Criação de Sets a partir dos elementos normalizados (sem SOURCE_CODE) - standard_elements_normalized = [normalize_element_for_comparison(item) for item in standard_elements_filtered] - client_elements_normalized = [normalize_element_for_comparison(item) for item in client_elements_filtered] + # Usamos _remove_source_code para a comparação (como "normalizer") + standard_elements_normalized = [_remove_source_code(item) for item in standard_elements_filtered] + client_elements_normalized = [_remove_source_code(item) for item in client_elements_filtered] try: standard_set = {json.dumps(item, sort_keys=True) for item in standard_elements_normalized} @@ -231,24 +234,31 @@ def compare_structures(standard_structure: Dict[str, Any], client_structure: Dic return audit_log -# --- CLASSE PRINCIPAL DE SERVIÇO (APLICA FILTRO EM DEBUG STRUCTURES) --- +# --- CLASSE PRINCIPAL DE SERVIÇO --- class ShowDatabaseService: - # NEW HELPER: Filtra SOURCE_CODE das estruturas de DEBUG - def _filter_source_code_recursively(self, structure: Dict[str, Any]) -> Dict[str, Any]: - """Remove SOURCE_CODE de qualquer elemento em um dicionário de estrutura.""" - # Usa json.dumps/loads para uma cópia profunda eficiente - filtered_structure = json.loads(json.dumps(structure)) + # Novo Helper: Função dedicada para limpar a estrutura completa de debug antes do retorno + def _clean_full_structure_for_output(self, structure: Dict[str, Any]) -> Dict[str, Any]: + """Cria uma cópia limpa da estrutura, removendo 'SOURCE_CODE' em todos os elementos relevantes.""" + # Garante deep copy de toda a estrutura + cleaned = json.loads(json.dumps(structure)) - keys_to_filter = ['tables', 'views', 'procedures', 'triggers', 'primary_keys', 'foreign_keys', 'indexes'] + keys_to_clean = ['tables', 'views', 'procedures', 'triggers', 'primary_keys', 'foreign_keys', 'indexes'] - for key in keys_to_filter: - if key in filtered_structure and isinstance(filtered_structure[key], list): - # Filtra a lista inteira, usando normalize_element_for_comparison que já lida com SOURCE_CODE - filtered_structure[key] = [normalize_element_for_comparison(item) for item in filtered_structure[key]] + for key in keys_to_clean: + if key in cleaned and isinstance(cleaned[key], list): + # Aplica a limpeza a cada item da lista usando a função helper _remove_source_code + cleaned[key] = [_remove_source_code(item) for item in cleaned[key]] - return filtered_structure + # Garante que, se houver campos (FIELDS) aninhados, eles também sejam limpos (apesar de SOURCE_CODE + # não ser comum em FIELDS, é uma camada extra de segurança) + if 'tables' in cleaned and isinstance(cleaned['tables'], list): + for table in cleaned['tables']: + if 'FIELDS' in table and isinstance(table['FIELDS'], list): + table['FIELDS'] = [_remove_source_code(field) for field in table['FIELDS']] + + return cleaned def execute(self, client_id_schema: LogClientIdSchema): @@ -272,13 +282,13 @@ class ShowDatabaseService: # Efetua a auditoria auditoria_do_banco = compare_structures( - standard_structure_data, # Estrutura padrão - client_structure # Estrutura do cliente + standard_structure_data, + client_structure ) - # Filtra SOURCE_CODE das estruturas de DEBUG antes de retornar - debug_cliente = self._filter_source_code_recursively(client_structure) - debug_padrao = self._filter_source_code_recursively(standard_structure_data) + # Filtra SOURCE_CODE das estruturas de DEBUG usando o novo helper + debug_cliente = self._clean_full_structure_for_output(client_structure) + debug_padrao = self._clean_full_structure_for_output(standard_structure_data) # Monta o JSON final data = { @@ -292,10 +302,10 @@ class ShowDatabaseService: "db_accessible": database_data.get("db_accessible", {}), "last_modified": database_data.get("last_modified", {}), - # --- CAMPOS DE DEBUG (AGORA FILTRADOS) --- + # --- CAMPOS DE DEBUG (AGORA TOTALMENTE FILTRADOS) --- "estrutura_cliente_debug": debug_cliente, "estrutura_padrao_debug": debug_padrao, - # ---------------------------------------- + # ---------------------------------------------------- "auditoria_do_banco": auditoria_do_banco }