655 lines
30 KiB
Python
655 lines
30 KiB
Python
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()
|