from datetime import datetime as dt # pyrefly: ignore [missing-import] from pydantic import ValidationError, TypeAdapter from json.decoder import JSONDecodeError from Exchange2 import QueueExchange2, LoggerExchange2 from exchangeModels import * from HostMetrics import * from appIC2Builder import * from services.cliente import ClienteService from services.nfe import NfeService from services.titulo_receber import TituloReceberService from db.banco import Banco from models.recebimento import Recebimento, RecebimentoPlugnotas from models.sg_tray_models.services_model import TrayOrderRootResponse from api.tray import ApiTray from send_rpc import SendRPCService from send_queue import SendQueueService import xml.etree.ElementTree as ET import base64 import redis import json import time import sys # Versão do script e histórico básico version = "1" versionstr = f"v{version}.0.0 - BALT - 24/04/2026 - VERSÃO INICIAL" system = "innovar_amr_tray" service = "controller" tenant = "innovar" startup_date = dt.now().strftime("%Y-%m-%d %H:%M:%S") TaskCount = 0 metrics = HostMetrics() stats = metrics.get_metrics() # Obtém o nome do ambiente/container try: with open("/app/hostname") as f: origin= f.read().strip() except Exception as e: print(f"Montar o arquivo hostname no compose: {e}", flush=True) time.sleep(5) sys.exit(0) ############################################################## < Inicio logica > ############################################################## def buscar_dados_tray(id_pedido_tray) -> TrayOrderRootResponse | None: step_status = "BUSCANDO PEDIDO NO TRAY" logger.logIC2(realm=RealmType.OPERATIONAL,msg=(step_status,"INICIADO",OpStatus.ACTIVE)) try: api_tray = ApiTray(system_config=system_config, redis_client=rd) except Exception as e: message = f"Erro ao inicializar ApiTray: {e}" logger.logIC2(realm=RealmType.OPERATIONAL,msg=(step_status, message, OpStatus.ERROR)) return None try: pedido = api_tray.get_pedido_completo(id_pedido_tray) logger.logIC2(realm=RealmType.OPERATIONAL,msg=(step_status, f"Pedido encontrado: {pedido}", OpStatus.OK)) return pedido except Exception as e: message = f"Erro ao buscar pedido no Tray: {e}" logger.logIC2(realm=RealmType.OPERATIONAL,msg=(step_status, message, OpStatus.ERROR)) return None def criar_cliente(pedido: TrayOrderRootResponse, banco: Banco) -> int | None: step_status = "CRIANDO CLIENTE NO SIENGE" logger.logIC2(realm=RealmType.OPERATIONAL,msg=(step_status,"INICIADO",OpStatus.ACTIVE)) try: cliente_service = ClienteService(config=system_config, redis_client=rd) except Exception as e: message = f"Erro ao inicializar ClienteService: {e}" logger.logIC2(realm=RealmType.OPERATIONAL,msg=(step_status, message, OpStatus.ERROR)) logger.logMsgError(f"Erro ao inicializar ClienteService: {e}") return False logger.logIC2(realm=RealmType.OPERATIONAL,msg=(step_status,"BUSCANDO CONFIGURAÇÃO DO CLIENTE",OpStatus.ACTIVE)) try: config_tenant = banco.get_config_cliente(tenant=tenant) if not config_tenant: message = f"Configuração do cliente '{tenant}' não encontrada no banco de dados." logger.logIC2(realm=RealmType.OPERATIONAL,msg=(step_status, message, OpStatus.ERROR)) return False except Exception as e: message = f"Erro ao obter configuração do cliente: {e}" logger.logIC2(realm=RealmType.OPERATIONAL,msg=(step_status, message, OpStatus.ERROR)) return False logger.logIC2(realm=RealmType.OPERATIONAL,msg=(step_status,"MAPPING DOS DADOS",OpStatus.ACTIVE)) try: payload = cliente_service._mapper_tray_to_sienge_cliente(pedido, config_tenant) except Exception as e: print(f"Erro ao mapear cliente: {e}",flush=True) message = f"Erro ao mapear dados do cliente: {e}" logger.logIC2(realm=RealmType.OPERATIONAL,msg=(step_status, message, OpStatus.ERROR)) return False logger.logIC2(realm=RealmType.OPERATIONAL,msg=(step_status,"BUSCANDO CREDENCIAIS DO INTEGRADOR",OpStatus.ACTIVE)) try: integrador = banco.get_credenciais_servicos_integradores(integrador="cliente") if not integrador: message = f"Credenciais para integrador 'cliente' não encontradas no banco de dados." logger.logIC2(realm=RealmType.OPERATIONAL,msg=(step_status, message, OpStatus.ERROR)) return False except Exception as e: message = f"Erro ao obter credenciais do integrador: {e}" logger.logIC2(realm=RealmType.OPERATIONAL,msg=(step_status, message, OpStatus.ERROR)) return False logger.logIC2(realm=RealmType.OPERATIONAL,msg=(step_status,"ENVIANDO DADOS PARA FILA DE CLIENTE (RPC)",OpStatus.ACTIVE)) try: rpc = SendRPCService( system = integrador.system, service = integrador.service, amqps = integrador.amqps, origin = origin, serviceid = integrador.serviceid, servicekey = integrador.servicekey ) print(payload, flush=True) response = rpc.send_rpc(payload=payload) payload = response.get('payload') hmac = response.get('hmac') if not payload or not hmac: message = f"Resposta RPC inválida: {response}" logger.logIC2(realm=RealmType.OPERATIONAL,msg=(step_status, message, OpStatus.ERROR)) return False response_data = rpc.get_payload(hmac, payload) logger.logIC2(realm=RealmType.OPERATIONAL,msg=(step_status, f"Cliente criado: {response_data.get('customer_id')}", OpStatus.OK)) return response_data.get('customer_id') except Exception as e: message = f"Erro ao enviar dados para fila de cliente: {e}" logger.logIC2(realm=RealmType.OPERATIONAL,msg=(step_status, message, OpStatus.ERROR)) return False def criar_titulo(pedido: TrayOrderRootResponse, banco: Banco, chave_nfe: str, numero_nfe: str) -> int | None: step_status = "CRIANDO TÍTULO A RECEBER NO SIENGE" logger.logIC2(realm=RealmType.OPERATIONAL,msg=(step_status,"INICIADO",OpStatus.ACTIVE)) try: titulo_service = TituloReceberService(config=system_config) except Exception as e: message = f"Erro ao inicializar TituloReceberService: {e}" logger.logIC2(realm=RealmType.OPERATIONAL,msg=(step_status, message, OpStatus.ERROR)) return False logger.logIC2(realm=RealmType.OPERATIONAL,msg=(step_status,"BUSCANDO CONFIGURAÇÃO DO CLIENTE",OpStatus.ACTIVE)) try: config_tenant = banco.get_config_cliente(tenant=tenant) if not config_tenant: message = f"Configuração do cliente '{tenant}' não encontrada no banco de dados." logger.logIC2(realm=RealmType.OPERATIONAL,msg=(step_status, message, OpStatus.ERROR)) return False except Exception as e: message = f"Erro ao obter configuração do cliente: {e}" logger.logIC2(realm=RealmType.OPERATIONAL,msg=(step_status, message, OpStatus.ERROR)) return False logger.logIC2(realm=RealmType.OPERATIONAL,msg=(step_status,"BUSCANDO APROPRIAÇÃO FINANCEIRA",OpStatus.ACTIVE)) try: apropriacao = banco.get_lista_apropriacao_financeira(tenant=tenant) if not apropriacao: message = f"Apropriação financeira para tenant '{tenant}' não encontrada no banco de dados." logger.logIC2(realm=RealmType.OPERATIONAL,msg=(step_status, message, OpStatus.ERROR)) return False except Exception as e: message = f"Erro ao obter apropriação financeira: {e}" logger.logIC2(realm=RealmType.OPERATIONAL,msg=(step_status, message, OpStatus.ERROR)) return False logger.logIC2(realm=RealmType.OPERATIONAL,msg=(step_status,"BUSCANDO PEDIDO",OpStatus.ACTIVE)) try: pedido_db = banco.get_pedido(id_pedido_tray=pedido.Order.id) if not pedido_db: message = f"Pedido '{pedido.id}' não encontrado no banco de dados." logger.logIC2(realm=RealmType.OPERATIONAL,msg=(step_status, message, OpStatus.ERROR)) return False except Exception as e: message = f"Erro ao obter pedido: {e}" logger.logIC2(realm=RealmType.OPERATIONAL,msg=(step_status, message, OpStatus.ERROR)) return False logger.logIC2(realm=RealmType.OPERATIONAL,msg=(step_status,"MAPPING DOS DADOS",OpStatus.ACTIVE)) try: payload = titulo_service.map_tray_order_to_bill_data(pedido, config_tenant, apropriacao, pedido_db, chave_nfe, numero_nfe) except Exception as e: message = f"Erro ao mapear dados: {e}" logger.logIC2(realm=RealmType.OPERATIONAL,msg=(step_status, message, OpStatus.ERROR)) return False logger.logIC2(realm=RealmType.OPERATIONAL,msg=(step_status,"BUSCANDO CREDENCIAIS DO INTEGRADOR",OpStatus.ACTIVE)) try: integrador = banco.get_credenciais_servicos_integradores(integrador="titulo-cr") if not integrador: message = f"Credenciais para integrador 'titulo-cr' não encontradas no banco de dados." logger.logIC2(realm=RealmType.OPERATIONAL,msg=(step_status, message, OpStatus.ERROR)) return False except Exception as e: message = f"Erro ao obter credenciais do integrador: {e}" logger.logIC2(realm=RealmType.OPERATIONAL,msg=(step_status, message, OpStatus.ERROR)) return False logger.logIC2(realm=RealmType.OPERATIONAL,msg=(step_status,"ENVIANDO DADOS PARA FILA DE TÍTULO A RECEBER (RPC)",OpStatus.ACTIVE)) try: rpc = SendRPCService( system = integrador.system, service = integrador.service, amqps = integrador.amqps, origin = origin, serviceid = integrador.serviceid, servicekey = integrador.servicekey ) response = rpc.send_rpc(payload=payload.model_dump(exclude_none=True)) payload = response.get('payload') hmac = response.get('hmac') if not payload or not hmac: message = f"Resposta RPC inválida: {response}" logger.logIC2(realm=RealmType.OPERATIONAL,msg=(step_status, message, OpStatus.ERROR)) return False response_data = rpc.get_payload(hmac, payload) logger.logIC2(realm=RealmType.OPERATIONAL,msg=(step_status, f"Título a receber criado: {response_data.get('id_titulo')}", OpStatus.OK)) return response_data.get('id_titulo') except Exception as e: print(f"Erro ao enviar dados para título a receber: {e}", flush=True) message = f"Erro ao enviar dados para fila de título a receber: {e}" logger.logIC2(realm=RealmType.OPERATIONAL,msg=(step_status, message, OpStatus.ERROR)) return False def criar_nfe(pedido: TrayOrderRootResponse, banco: Banco) -> bool: step_status = "NFe - CRIACAO" logger.logIC2(realm=RealmType.OPERATIONAL,msg=(step_status,"INICIADO",OpStatus.ACTIVE)) try: nfe = NfeService(system_config, rd) except Exception as e: message = f"Erro ao inicializar NFeService: {e}" logger.logIC2(realm=RealmType.OPERATIONAL,msg=(step_status, message, OpStatus.ERROR)) return False logger.logIC2(realm=RealmType.OPERATIONAL,msg=(step_status,"BUSCANDO CONFIGURAÇÃO DO CLIENTE",OpStatus.ACTIVE)) try: config_tenant = banco.get_config_cliente(tenant=tenant) if not config_tenant: message = f"Configuração do cliente '{tenant}' não encontrada no banco de dados." logger.logIC2(realm=RealmType.OPERATIONAL,msg=(step_status, message, OpStatus.ERROR)) return False except Exception as e: message = f"Erro ao obter configuração do cliente: {e}" logger.logIC2(realm=RealmType.OPERATIONAL,msg=(step_status, message, OpStatus.ERROR)) return False logger.logIC2(realm=RealmType.OPERATIONAL,msg=(step_status,"MAPPING DOS DADOS",OpStatus.ACTIVE)) try: payload = nfe._mapper_pedido_tray_to_nfe(pedido, config_tenant) except Exception as e: message = f"Erro ao mapear dados: {e}" logger.logIC2(realm=RealmType.OPERATIONAL,msg=(step_status, message, OpStatus.ERROR)) return False logger.logIC2(realm=RealmType.OPERATIONAL,msg=(step_status,"BUSCANDO CREDENCIAIS DO INTEGRADOR",OpStatus.ACTIVE)) try: integrador = banco.get_credenciais_servicos_integradores(integrador="nfe") if not integrador: message = f"Credenciais para integrador 'nfe' não encontradas no banco de dados." logger.logIC2(realm=RealmType.OPERATIONAL,msg=(step_status, message, OpStatus.ERROR)) return False except Exception as e: message = f"Erro ao obter credenciais do integrador: {e}" logger.logIC2(realm=RealmType.OPERATIONAL,msg=(step_status, message, OpStatus.ERROR)) return False logger.logIC2(realm=RealmType.OPERATIONAL,msg=(step_status,"ENVIANDO DADOS PARA FILA DE NFE (QUEUE)",OpStatus.ACTIVE)) try: queue = SendQueueService( system = integrador.system, service = integrador.service, amqps = integrador.amqps, origin = origin, serviceid = integrador.serviceid, servicekey = integrador.servicekey ) queue.send_queue(payload=payload.model_dump()) logger.logIC2(realm=RealmType.OPERATIONAL,msg=(step_status, "Dados enviados para fila de NFe", OpStatus.OK)) return True except Exception as e: message = f"Erro ao enviar dados para fila de NFe: {e}" logger.logIC2(realm=RealmType.OPERATIONAL,msg=(step_status, message, OpStatus.ERROR)) return False def atualizar_nfe_tray(id_pedido_tray: str, xml: str, banco: Banco) -> bool: step_status = "NFe - ATUALIZACAO TRAY" logger.logIC2(realm=RealmType.OPERATIONAL,msg=(step_status,"Localizando dados no XML",OpStatus.ACTIVE)) try: ns = {"nfe": "http://www.portalfiscal.inf.br/nfe"} root = ET.fromstring(xml) chave = root.find(".//nfe:chNFe", ns) data_emissao = root.find(".//nfe:dhEmi", ns) serie = root.find(".//nfe:serie", ns) value = root.find(".//nfe:vNF", ns) numero = root.find(".//nfe:nNF", ns) chave = chave.text if chave is not None else None data_emissao = data_emissao.text if data_emissao is not None else None serie = serie.text if serie is not None else None value = value.text if value is not None else None numero = numero.text if numero is not None else None if not all([chave, data_emissao, serie, value, numero]): message = "Dados necessários não encontrados no XML" logger.logIC2(realm=RealmType.OPERATIONAL,msg=(step_status, message, OpStatus.ERROR)) return False itens = root.findall(".//nfe:det", ns) produtos = [] for item in itens: cProd = item.find(".//nfe:cProd", ns) xProd = item.find(".//nfe:xProd", ns) cfop = item.find(".//nfe:CFOP", ns) produtos.append({ "product_id" : cProd.text if cProd is not None else None, "variation_id": xProd.text if xProd is not None else None, "cfop" : cfop.text if cfop is not None else None }) payload = { "issue_date" : data_emissao[:10], "number" : numero, "serie" : serie, "value" : value, "key" : chave, "link" : None, "xml_danfe" : xml, "ProductCfop": produtos } except Exception as e: message = f"Erro ao extrair dados do XML da NFe: {e}" logger.logIC2(realm=RealmType.OPERATIONAL,msg=(step_status, message, OpStatus.ERROR)) return False step_status = "NFe - ATUALIZACAO TRAY" logger.logIC2(realm=RealmType.OPERATIONAL,msg=(step_status,"Enviando dados para atualização do pedido no Tray",OpStatus.ACTIVE)) try: api_tray = ApiTray(system_config=system_config, redis_client=rd) api_tray.inserir_nfe_pedido(id_pedido=id_pedido_tray, nfe=payload) logger.logIC2(realm=RealmType.OPERATIONAL,msg=(step_status, "Dados enviados para atualização do pedido no Tray", OpStatus.OK)) # return True except Exception as e: message = f"Erro ao enviar dados para atualização do pedido no Tray: {e}" logger.logIC2(realm=RealmType.OPERATIONAL,msg=(step_status, message, OpStatus.ERROR)) # return False step_status = "ATUALIZANDO NFe NO BANCO" logger.logIC2(realm=RealmType.OPERATIONAL,msg=(step_status,"INICIADO",OpStatus.ACTIVE)) try: banco.update_pedido_nfe(id_pedido_tray = id_pedido_tray, status="Faturado", nfe_gerada = True,nfe_numero=numero,nfe_serie=serie) logger.logIC2(realm=RealmType.OPERATIONAL,msg=(step_status, "NFe atualizada no banco de dados", OpStatus.OK)) return True except Exception as e: message = f"Erro ao atualizar NFe no banco de dados: {e}" logger.logIC2(realm=RealmType.OPERATIONAL,msg=(step_status, message, OpStatus.ERROR)) return False ############################################################## < Fim logica > ############################################################## def sendStatus(logger: LoggerExchange2): global TaskCount, stats TaskCount += 1 stats = metrics.get_metrics() cpu_p, cores, load_1, load_5, load_15, m_total, m_used, m_free, m_pct, net_up, net_down, net_total, disk_usage = stats logger.logIC2(realm = RealmType.STATUS, msg = (TaskCount, cpu_p, m_pct, disk_usage, net_total)) def tratar_recebimento_webhook_tray(recebimento: Recebimento): logger.logMsg(f"Tratando recebimento do webhook Tray: {recebimento}") if recebimento.data.scope_name != "order": logger.logMsg(f"Escopo desconhecido: {recebimento.data.scope_name}") return logger.ic2_builder.dados.task_id = recebimento.data.scope_id dados_tray = buscar_dados_tray(recebimento.data.scope_id) if not dados_tray: logger.logMsgError("Erro ao buscar dados do pedido no Tray. Verifique os logs para mais detalhes.") return step_status = "INICIANDO BANCO DE DADOS" logger.logIC2(realm=RealmType.OPERATIONAL,msg=(step_status, "Iniciando conexão com o banco de dados", OpStatus.ACTIVE)) try: banco = Banco(database = system_config.db_name, user = system_config.db_user, password = system_config.db_password, host = system_config.db_host, port = system_config.db_port) logger.logIC2(realm=RealmType.OPERATIONAL,msg=(step_status, "Banco de dados inicializado com sucesso", OpStatus.OK)) except Exception as e: message = f"Erro ao conectar ao banco de dados: {e}" logger.logIC2(realm=RealmType.OPERATIONAL,msg=(step_status, message, OpStatus.ERROR)) return step_status = "INSERINDO PEDIDO NO BANCO CASO NÃO EXISTA" logger.logIC2(realm=RealmType.OPERATIONAL,msg=(step_status, "Iniciando inserção do pedido no banco de dados caso não exista", OpStatus.ACTIVE)) try: banco.upsert_pedido(id_pedido_tray=recebimento.data.scope_id, status=recebimento.data.act, tenant=tenant) logger.logIC2(realm=RealmType.OPERATIONAL,msg=(step_status, "Pedido inserido no banco de dados com sucesso", OpStatus.OK)) except Exception as e: message = f"Erro ao inserir pedido no banco de dados: {e}" logger.logIC2(realm=RealmType.OPERATIONAL,msg=(step_status, message, OpStatus.ERROR)) return match recebimento.data.act: case "insert": cliente_id = criar_cliente(dados_tray, banco) if not cliente_id: return step_status = "ATUALIZANDO CLIENTE NO PEDIDO (DB)" logger.logIC2(RealmType.OPERATIONAL,msg=(step_status, "Iniciando atualização do cliente no pedido", OpStatus.ACTIVE)) try: banco.update_pedido_cliente(id_pedido_tray=recebimento.data.scope_id, codigo_cliente=cliente_id) logger.logIC2(RealmType.OPERATIONAL,msg=(step_status, "Cliente atualizado no pedido com sucesso", OpStatus.OK)) except Exception as e: message = f"Erro ao atualizar cliente no pedido: {e}" logger.logIC2(RealmType.OPERATIONAL,msg=(step_status, message, OpStatus.ERROR)) return case "update": if dados_tray.Order.status.upper() != "A ENVIAR": logger.logMsgError(f"Status do pedido diferente do esperado {dados_tray.Order.status.upper()}") nfe = criar_nfe(dados_tray, banco) if not nfe: return step_status = "ATUALIZANDO ENVIADO PLUGNOTAS NO PEDIDO (DB)" logger.logIC2(RealmType.OPERATIONAL,msg=(step_status, "Atualizando pedido no banco", OpStatus.ACTIVE)) try: banco.update_pedido_enviado_plugnotas(id_pedido_tray=recebimento.data.scope_id, enviado_plugnotas=True) logger.logIC2(RealmType.OPERATIONAL,msg=(step_status, "enviado_plugnotas atualizado no banco", OpStatus.OK)) except Exception as e: message = f"Erro ao atualizar enviado_plugnotas no pedido: {e}" logger.logIC2(RealmType.OPERATIONAL,msg=(step_status, message, OpStatus.ERROR)) return case _: logger.logMsg(f"Ação desconhecida: {recebimento.data.act}") return time.sleep(0.5) return True def tratar_webhook_plugnotas(recebimento: RecebimentoPlugnotas): print(f"WebHook recebido do PlugNotas: {recebimento}", flush=True) if recebimento.status.upper() != "CONCLUIDO": logger.logMsgError(f"Status do webhook do PlugNotas diferente do esperado: {recebimento.status}") return id_pedido_tray = recebimento.idIntegracao.split("_")[1] dados_tray = buscar_dados_tray(id_pedido_tray) if not dados_tray: logger.logMsgError(f"Erro ao buscar dados do pedido no Tray: {id_pedido_tray}") return step_status = "INICIANDO BANCO DE DADOS" logger.logIC2(realm=RealmType.OPERATIONAL,msg=(step_status, "Iniciando conexão com o banco de dados", OpStatus.ACTIVE)) try: banco = Banco(database = system_config.db_name, user = system_config.db_user, password = system_config.db_password, host = system_config.db_host, port = system_config.db_port) logger.logIC2(realm=RealmType.OPERATIONAL,msg=(step_status, "Banco de dados inicializado com sucesso", OpStatus.OK)) except Exception as e: message = f"Erro ao conectar ao banco de dados: {e}" logger.logIC2(realm=RealmType.OPERATIONAL,msg=(step_status, message, OpStatus.ERROR)) return step_status = "BUSCANDO CHAVE DE ACESSO DA NFE" logger.logIC2(realm=RealmType.OPERATIONAL,msg=(step_status, "Buscando chave de acesso da NFe no banco de dados", OpStatus.ACTIVE)) try: xml = base64.b64decode(recebimento.xml_base64).decode() ns = {"nfe": "http://www.portalfiscal.inf.br/nfe"} root = ET.fromstring(xml) chave_nfe = root.find(".//nfe:chNFe", ns) numero = root.find(".//nfe:nNF", ns) if chave_nfe is not None and numero is not None: chave_nfe = chave_nfe.text numero_nfe = numero.text logger.logIC2(realm=RealmType.OPERATIONAL,msg=(step_status, f"Chave de acesso da NFe encontrada: {chave_nfe}", OpStatus.ACTIVE)) else: message = "Chave de acesso da NFe não encontrada no XML" logger.logIC2(realm=RealmType.OPERATIONAL,msg=(step_status, message, OpStatus.ERROR)) return except Exception as e: message = f"Erro ao buscar chave de acesso da NFe: {e}" logger.logIC2(realm=RealmType.OPERATIONAL,msg=(step_status, message, OpStatus.ERROR)) return titulo = criar_titulo(dados_tray, banco, chave_nfe, numero_nfe) if not titulo: return step_status = "ATUALIZANDO TITULO NO PEDIDO NO BANCO" logger.logIC2(realm=RealmType.OPERATIONAL,msg=(step_status, "Iniciando atualização do titulo no pedido no banco", OpStatus.ACTIVE)) try: banco.update_pedido_titulo(id_pedido_tray=id_pedido_tray, titulo_gerado=titulo) logger.logIC2(realm=RealmType.OPERATIONAL,msg=(step_status, "Titulo atualizado no pedido no banco com sucesso", OpStatus.OK)) except Exception as e: print(f"Erro ao atualizar titulo no pedido no banco: {e}", flush=True) message = f"Erro ao atualizar titulo no pedido no banco: {e}" logger.logIC2(realm=RealmType.OPERATIONAL,msg=(step_status, message, OpStatus.ERROR)) return step_status = "ATUALIZANDO NFE NO TRAY" logger.logIC2(realm=RealmType.OPERATIONAL,msg=(step_status, "Iniciando atualização da NFe no Tray", OpStatus.ACTIVE)) if not atualizar_nfe_tray(id_pedido_tray, xml): logger.logMsgError("Erro ao atualizar NFe no Tray. Verifique os logs para mais detalhes.") return logger.logIC2(realm=RealmType.OPERATIONAL,msg=(step_status, "NFe atualizada no Tray com sucesso", OpStatus.OK)) def callback(ch, method, properties, body): # Controlador de mensagens do RabbitMQ: decodifica a mensagem e inicia o processo de clonagem. global logger sendStatus(logger) logger.logMsg(f"Mensagem recebida: {body}") # Confirma o recebimento da mensagem (ACK) para remover da fila ch.basic_ack(delivery_tag=method.delivery_tag) dado = json.loads(body) hmac = dado['hmac'] payload = dado['payload'] if not hmac or not payload: logger.logMsg("HMAC ou Payload inválido") return exchange.setCrypto(serviceid=system_config.serviceid, servicekey=system_config.servicekey) if not exchange.getPayload(hmac, payload): logger.logMsg("Falha ao descifrar payload") return payload_dict = json.loads(exchange.payload) if not payload_dict: logger.logMsg("Payload inválido") return # Verifica qual modelo de recebimento é compativel - PayloadModel = Recebimento | RecebimentoPlugnotas adapter = TypeAdapter(PayloadModel) try: logger.logMsg(f"Validando payload recebido: {payload_dict}") recebimento = adapter.validate_python(payload_dict) if isinstance(recebimento, Recebimento): logger.logMsg("Payload validado como Recebimento do webhook Tray") tratar_recebimento_webhook_tray(recebimento) elif isinstance(recebimento, RecebimentoPlugnotas): logger.logMsg("Payload validado como Recebimento do webhook PlugNotas") tratar_webhook_plugnotas(recebimento) else: logger.logMsgError("Modelo de recebimento fora do padrão") return except Exception as e: logger.logMsgError(f"Erro ao converter recebimento \n {recebimento} \n {e}") return # --- Lógica de Inicialização do Script --- # CONFIGURAÇÃO SERVIÇO REDIS try: rd = redis.Redis(host='redis', port=6379, decode_responses=True) key = f"{system}-system_config-{tenant}" if not rd.exists(key): msg = f"Key '{key}' not found in Redis." print(msg, flush=True) time.sleep(5) sys.exit(0) except Exception as e: print(f"Error connecting to Redis: A {e}", flush=True) time.sleep(5) sys.exit(0) # VALIDA JSON try: configRaw = rd.get(key) configJS = json.loads(configRaw) except JSONDecodeError as e: print(f"Error connecting to Redis: B {e}", flush=True) time.sleep(5) sys.exit(0) except Exception as e: print(f"Error REDIS GET KEY {key}: {e}", flush=True) time.sleep(5) sys.exit(0) # VALIDA QUALIDADE DO JSON try: system_config = SystemConfig(**configJS) except ValidationError as e: print(f"Error connecting to Redis: C {e}", flush=True) time.sleep(5) sys.exit(0) # Estruturas de dados para logging e telemetria dados = Dados( service_date = dt.now().strftime("%Y-%m-%d %H:%M:%S"), # INICIO DO TRABALHO - FICA FIXO ATÉ FINAL DO TRABALHO startup_date = startup_date, task_id = "00000000", #secrets.token_hex(8).upper(), service = service, versionstr = versionstr, origin = origin, enterprise_id = system_config.enterprise_id, enterprise_name = system_config.enterprise_name, system = system ) logger = LoggerExchange2( ic2_builder = AppIC2Builder(dados), amqps = system_config.ic2_url, system = system_config.system, service = service, version = versionstr, origin = origin, client = tenant, logType = "logs", logLocal = True ) try: exchange = QueueExchange2( amqps = system_config.amqps, origin = origin, system = system, service = service, version = versionstr, # client = tenant, callback= callback) except Exception as e: print(f"Erro conectando a fila: {e}", flush=True) time.sleep(5) sys.exit(0) # Inicialização operacional logger.logMsg(f"{system.upper()} - SERVIÇO DE RESERVAS v{version}") # Inicia o consumo perpétuo da fila exchange.start_consuming()