import json import logging import os import requests from src.models.erro_holmes import ErroHolmes from src.models.estoque_homes import EstoqueHolmes from src.models.proposta import Proposta from src.models.resultado import Resultado from src.repositories.estoque_repository import EstoqueRepository from src.utils.utils import extrair_proposta class HolmesAPI: def __init__(self): self.headers = { # "authorization": self._token_usuario(), "api_token": 'eyJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiNmE4MzBjMzcwNDdlNzI1MTVlMDU1ZDFhIiwiaWF0IjoxNzg2OTczMjM5fQ.K-R2E6v7JjCJDJJfDhyZ8nwQwMiaVfbF2BtUvW-sNwQ', "Content-Type": "application/json" } def _somente_digitos(self, valor) -> str: return ''.join(c for c in str(valor or '') if c.isdigit()) def _token_usuario(self) -> str: url = "https://app-api.holmesdoc.io/v1/session" body = {"email": os.getenv('HOLMES_USER'), "password": os.getenv('HOLMES_PASS')} headers = {"Content-Type": "application/json", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/151.0.0.0 Safari/537.36"} response = requests.post(url, json=body, headers=headers) response.raise_for_status() dados = response.json() if "token" not in dados: logging.error( f"Login Holmes sem token (HTTP {response.status_code}): {str(dados)[:500]}" ) raise RuntimeError("Login Holmes não retornou token") return dados["token"] def _build_payload_novos(self, proposta: Proposta) -> dict: start_event = 'StartEvent_1' campos = [ ("e88ea290-8ce4-11f1-9f28-e51e49945850", proposta.empresa_holmes), ("ed2d30f0-8ce4-11f1-9f28-e51e49945850", proposta.tipo_pessoa), ("f2fe24d0-8ce4-11f1-9f28-e51e49945850", proposta.usado_na_troca), ("2aafcff0-8cf4-11f1-9f28-e51e49945850", proposta.forma_pagamento), ("fad87d40-8ce4-11f1-9f28-e51e49945850", proposta.proposta_apollo), ("fdfd63f0-8ce4-11f1-9f28-e51e49945850", proposta.veiculo), ("01109760-8ce5-11f1-9f28-e51e49945850", proposta.chassi), ("04ab7160-8ce5-11f1-9f28-e51e49945850", proposta.des_modelo), ("1b0974c0-8ce5-11f1-9f28-e51e49945850", proposta.valor_proposta), ("23914b40-8ce5-11f1-9f28-e51e49945850", proposta.nome), ("27b419f0-8ce5-11f1-9f28-e51e49945850", self._somente_digitos(proposta.cpfcnpj)), ("398ac070-8ce5-11f1-9f28-e51e49945850", self._somente_digitos(proposta.celular)), ("3e7bb490-8ce5-11f1-9f28-e51e49945850", proposta.email), ("6873d880-9ccc-11f1-b919-f777409ec14c", proposta.vendedor_holmes), ] payload = { "workflow": { "start_event": start_event, "property_values": [ {"id": prop_id, "value": valor} for prop_id, valor in campos if valor is not None and str(valor).strip() != '' ], "whats": "", "documents": [], "test": False } } logging.debug("Payload proposta %s: %s", proposta.proposta_apollo, payload) return payload def _build_payload_usados(self, proposta: Proposta) -> dict: start_event = 'StartEvent_1' campos = [ ("e88ea290-8ce4-11f1-9f28-e51e49945850", proposta.empresa_holmes), ("ed2d30f0-8ce4-11f1-9f28-e51e49945850", proposta.tipo_pessoa), ("2aafcff0-8cf4-11f1-9f28-e51e49945850", proposta.forma_pagamento), ("f2fe24d0-8ce4-11f1-9f28-e51e49945850", proposta.usado_na_troca), ("fad87d40-8ce4-11f1-9f28-e51e49945850", proposta.proposta_apollo), ("fdfd63f0-8ce4-11f1-9f28-e51e49945850", proposta.veiculo), ("01109760-8ce5-11f1-9f28-e51e49945850", proposta.chassi), ("04ab7160-8ce5-11f1-9f28-e51e49945850", proposta.des_modelo), ("08b38c20-8ce5-11f1-9f28-e51e49945850", proposta.placa), ("1b0974c0-8ce5-11f1-9f28-e51e49945850", proposta.valor_proposta), ("23914b40-8ce5-11f1-9f28-e51e49945850", proposta.nome), ("27b419f0-8ce5-11f1-9f28-e51e49945850", self._somente_digitos(proposta.cpfcnpj)), ("398ac070-8ce5-11f1-9f28-e51e49945850", self._somente_digitos(proposta.celular)), ("3e7bb490-8ce5-11f1-9f28-e51e49945850", proposta.email), ("19c78c10-9d92-11f1-ad38-41765eab56e3", proposta.vendedor_holmes), ] payload = { "workflow": { "start_event": start_event, "property_values": [ {"id": prop_id, "value": valor} for prop_id, valor in campos if valor is not None and str(valor).strip() != '' ], "whats": "", "documents": [], "test": False } } logging.debug("Payload proposta %s: %s", proposta.proposta_apollo, payload) return payload def _build_payload_imobilizado(self, proposta: Proposta) -> dict: start_event = 'StartEvent_1' campos = [ ("e88ea290-8ce4-11f1-9f28-e51e49945850", proposta.empresa_holmes), ("ed2d30f0-8ce4-11f1-9f28-e51e49945850", proposta.tipo_pessoa), ("f2fe24d0-8ce4-11f1-9f28-e51e49945850", proposta.usado_na_troca), ("2aafcff0-8cf4-11f1-9f28-e51e49945850", proposta.forma_pagamento), ("fad87d40-8ce4-11f1-9f28-e51e49945850", proposta.proposta_apollo), ("fdfd63f0-8ce4-11f1-9f28-e51e49945850", proposta.veiculo), ("01109760-8ce5-11f1-9f28-e51e49945850", proposta.chassi), ("04ab7160-8ce5-11f1-9f28-e51e49945850", proposta.des_modelo), ("08b38c20-8ce5-11f1-9f28-e51e49945850", proposta.placa), ("1b0974c0-8ce5-11f1-9f28-e51e49945850", proposta.valor_proposta), ("23914b40-8ce5-11f1-9f28-e51e49945850", proposta.nome), ("27b419f0-8ce5-11f1-9f28-e51e49945850", self._somente_digitos(proposta.cpfcnpj)), ("398ac070-8ce5-11f1-9f28-e51e49945850", self._somente_digitos(proposta.celular)), ("3e7bb490-8ce5-11f1-9f28-e51e49945850", proposta.email), ("d1b18d20-9d98-11f1-8298-cb4f6a31d606", proposta.vendedor_holmes), ] payload = { "workflow": { "start_event": start_event, "property_values": [ {"id": prop_id, "value": valor} for prop_id, valor in campos if valor is not None and str(valor).strip() != '' ], "whats": "", "documents": [], "test": False } } logging.debug("Payload proposta %s: %s", proposta.proposta_apollo, payload) return payload def _build_payload_venda_direta(self, proposta: Proposta) -> dict: # Esse formulario tem IDs proprios (nao reaproveita os dos outros tres), # nao tem Placa e traz a Observacao da proposta. start_event = 'StartEvent_1' campos = [ ("37897690-8d03-11f1-9f28-e51e49945850", proposta.empresa_holmes), ("420c59c0-8d03-11f1-9f28-e51e49945850", proposta.tipo_pessoa), ("46da1900-8d04-11f1-9f28-e51e49945850", proposta.forma_pagamento), ("48ee6f80-8d03-11f1-9f28-e51e49945850", proposta.usado_na_troca), ("53933290-8d03-11f1-9f28-e51e49945850", proposta.proposta_apollo), ("58d81310-8d03-11f1-9f28-e51e49945850", proposta.veiculo), ("5b19c5b0-8d03-11f1-9f28-e51e49945850", proposta.chassi), ("5f92a3a0-8d03-11f1-9f28-e51e49945850", proposta.des_modelo), ("6b95e540-8d03-11f1-9f28-e51e49945850", proposta.valor_proposta), ("73c56290-8d03-11f1-9f28-e51e49945850", proposta.nome), ("79635f90-8d03-11f1-9f28-e51e49945850", self._somente_digitos(proposta.cpfcnpj)), ("85ea9e40-8d03-11f1-9f28-e51e49945850", self._somente_digitos(proposta.celular)), ("8f16f220-8d03-11f1-9f28-e51e49945850", proposta.email), ("cbe61910-a2de-11f1-aff4-4f1f04587741", proposta.vendedor_holmes), ("e7610290-a2de-11f1-aff4-4f1f04587741", proposta.observacao), ] payload = { "workflow": { "start_event": start_event, "property_values": [ {"id": prop_id, "value": valor} for prop_id, valor in campos if valor is not None and str(valor).strip() != '' ], "whats": "", "documents": [], "test": False } } logging.debug("Payload proposta %s: %s", proposta.proposta_apollo, payload) return payload def existe_holmes(self, chassi: str, proposta: str) -> bool: """Confere se o chassi já está lançado no holmes e caso tenha o mesmo chassi ele bate a proposta Args: chassi (str): Chassi do veiculo vendido proposta (str): Proposta do veiculo Returns: bool: True caso existir e False caso não exista no holmes """ logging.info("Verificando se chassi %s (proposta %s) já existe no Holmes", chassi, proposta) url = 'https://app-api.holmesdoc.io/v2/search' body = { "query": { "from": 0, "size": 50, "context": "process", "sort": "updated_at", "order": "desc", "groups": [ { "match_all": True, "terms": [ { "value": f"{chassi}", "type": "match_phrase", "field": "_content" } ] } ] }, "trash": False, "deleted_by_me": False } resposta = requests.post(url, json=body, headers=self.headers) resposta.raise_for_status() dados = resposta.json() if dados['total'] == 0: logging.info("Chassi %s não encontrado no Holmes", chassi) return False PROCESSOS_VALIDOS = { 'Faturamento de Novos', 'Faturamento de Venda Direta', 'Faturamento de Test Drive', 'Faturamento de Usados', } docs_validos = [ doc for doc in dados.get('docs', []) if doc.get('name') in PROCESSOS_VALIDOS and doc.get('status') != 'canceled' ] if not docs_validos: logging.info("Chassi %s encontrado mas sem processos válidos (todos cancelados ou de outro template)", chassi) return False # proposta_holmes = extrair_proposta(docs_validos[0]['identifier']) # if str(proposta_holmes) != str(proposta): # logging.info("Chassi %s encontrado mas proposta diferente (Holmes: %s, Apollo: %s)", chassi, proposta_holmes, proposta) # return False logging.info("Chassi %s já existe no Holmes %s", chassi, proposta) return True def envia_fat_estoque_usado(self, proposta: Proposta, estoque_repo: EstoqueRepository) -> Resultado: logging.info("Enviando proposta %s para Holmes (empresa=%s, revenda=%s)", proposta.proposta_apollo, proposta.empresa, proposta.revenda) url = 'https://app-api.holmesdoc.io/v1/workflows/6a6cc58744c4ba86a63aebc1/start' payload = self._build_payload_usados(proposta) logging.debug("Payload montado para proposta %s", proposta.proposta_apollo) response = requests.post(url, headers=self.headers, data=json.dumps(payload)) logging.debug("Holmes respondeu com status %s para proposta %s", response.status_code, proposta.proposta_apollo) try: if response.status_code != 200: err_msg = f"Erro ao enviar para Holmes: {response.status_code} - {response.text or ''}" err_msg = (err_msg[:3900] + "...") if len(err_msg) > 3900 else err_msg logging.error("Falha ao enviar proposta %s: %s", proposta.proposta_apollo, err_msg) estoque_repo.insere_erro( ErroHolmes( empresa = proposta.empresa, revenda = proposta.revenda, proposta_apollo = proposta.proposta_apollo, motivo_erro= err_msg ) ) return Resultado(sucesso=False, mensagem=err_msg) else: resposta = response.json() logging.info("Proposta %s enviada com sucesso - processo Holmes: %s", proposta.proposta_apollo, resposta['id']) estoque_repo.insere_estoque( EstoqueHolmes( empresa= proposta.empresa, revenda= proposta.revenda, proposta_apollo= proposta.proposta_apollo, proesso_id= resposta['id'], usuario_criou= 'SUPORTE SISTEMAS', nome_processo= '[FAT] Faturamento de Estoque' ) ) return Resultado(sucesso=True, mensagem=resposta['id']) except Exception as e: logging.error("Erro inesperado ao processar proposta %s: %s", proposta.proposta_apollo, e, exc_info=True) return Resultado(sucesso=False, mensagem=str(e)) def envia_fat_estoque_novos(self, proposta: Proposta, estoque_repo: EstoqueRepository) -> Resultado: logging.info("Enviando proposta %s para Holmes (empresa=%s, revenda=%s)", proposta.proposta_apollo, proposta.empresa, proposta.revenda) url = 'https://app-api.holmesdoc.io/v1/workflows/6a6cbe67aff519bb6aa4b2d8/start' payload = self._build_payload_novos(proposta) logging.debug("Payload montado para proposta %s", proposta.proposta_apollo) response = requests.post(url, headers=self.headers, data=json.dumps(payload)) logging.debug("Holmes respondeu com status %s para proposta %s", response.status_code, proposta.proposta_apollo) try: if response.status_code != 200: err_msg = f"Erro ao enviar para Holmes: {response.status_code} - {response.text or ''}" err_msg = (err_msg[:3900] + "...") if len(err_msg) > 3900 else err_msg logging.error("Falha ao enviar proposta %s: %s", proposta.proposta_apollo, err_msg) estoque_repo.insere_erro( ErroHolmes( empresa = proposta.empresa, revenda = proposta.revenda, proposta_apollo = proposta.proposta_apollo, motivo_erro= err_msg ) ) return Resultado(sucesso=False, mensagem=err_msg) else: resposta = response.json() logging.info("Proposta %s enviada com sucesso - processo Holmes: %s", proposta.proposta_apollo, resposta['id']) estoque_repo.insere_estoque( EstoqueHolmes( empresa= proposta.empresa, revenda= proposta.revenda, proposta_apollo= proposta.proposta_apollo, proesso_id= resposta['id'], usuario_criou= 'SUPORTE SISTEMAS', nome_processo= '[FAT] Faturamento de Estoque' ) ) return Resultado(sucesso=True, mensagem=resposta['id']) except Exception as e: logging.error("Erro inesperado ao processar proposta %s: %s", proposta.proposta_apollo, e, exc_info=True) return Resultado(sucesso=False, mensagem=str(e)) def envia_fat_estoque_imobilizado(self, proposta: Proposta, estoque_repo: EstoqueRepository) -> Resultado: logging.info("Enviando proposta %s para Holmes (empresa=%s, revenda=%s)", proposta.proposta_apollo, proposta.empresa, proposta.revenda) url = 'https://app-api.holmesdoc.io/v1/workflows/6a6cc2a3dbf5173588777520/start' payload = self._build_payload_imobilizado(proposta) logging.debug("Payload montado para proposta %s", proposta.proposta_apollo) response = requests.post(url, headers=self.headers, data=json.dumps(payload)) logging.debug("Holmes respondeu com status %s para proposta %s", response.status_code, proposta.proposta_apollo) try: if response.status_code != 200: err_msg = f"Erro ao enviar para Holmes: {response.status_code} - {response.text or ''}" err_msg = (err_msg[:3900] + "...") if len(err_msg) > 3900 else err_msg logging.error("Falha ao enviar proposta %s: %s", proposta.proposta_apollo, err_msg) estoque_repo.insere_erro( ErroHolmes( empresa = proposta.empresa, revenda = proposta.revenda, proposta_apollo = proposta.proposta_apollo, motivo_erro= err_msg ) ) return Resultado(sucesso=False, mensagem=err_msg) else: resposta = response.json() logging.info("Proposta %s enviada com sucesso - processo Holmes: %s", proposta.proposta_apollo, resposta['id']) estoque_repo.insere_estoque( EstoqueHolmes( empresa= proposta.empresa, revenda= proposta.revenda, proposta_apollo= proposta.proposta_apollo, proesso_id= resposta['id'], usuario_criou= 'SUPORTE SISTEMAS', nome_processo= '[FAT] Faturamento de Estoque' ) ) return Resultado(sucesso=True, mensagem=resposta['id']) except Exception as e: logging.error("Erro inesperado ao processar proposta %s: %s", proposta.proposta_apollo, e, exc_info=True) return Resultado(sucesso=False, mensagem=str(e)) def envia_fat_estoque_venda_direta(self, proposta: Proposta, estoque_repo: EstoqueRepository) -> Resultado: logging.info("Enviando proposta %s para Holmes (empresa=%s, revenda=%s)", proposta.proposta_apollo, proposta.empresa, proposta.revenda) url = 'https://app-api.holmesdoc.io/v1/workflows/6a6cd6449341bbc7e45f29cf/start' payload = self._build_payload_venda_direta(proposta) logging.debug("Payload montado para proposta %s", proposta.proposta_apollo) response = requests.post(url, headers=self.headers, data=json.dumps(payload)) logging.debug("Holmes respondeu com status %s para proposta %s", response.status_code, proposta.proposta_apollo) try: if response.status_code != 200: err_msg = f"Erro ao enviar para Holmes: {response.status_code} - {response.text or ''}" err_msg = (err_msg[:3900] + "...") if len(err_msg) > 3900 else err_msg logging.error("Falha ao enviar proposta %s: %s", proposta.proposta_apollo, err_msg) estoque_repo.insere_erro( ErroHolmes( empresa = proposta.empresa, revenda = proposta.revenda, proposta_apollo = proposta.proposta_apollo, motivo_erro= err_msg ) ) return Resultado(sucesso=False, mensagem=err_msg) else: resposta = response.json() logging.info("Proposta %s enviada com sucesso - processo Holmes: %s", proposta.proposta_apollo, resposta['id']) estoque_repo.insere_estoque( EstoqueHolmes( empresa= proposta.empresa, revenda= proposta.revenda, proposta_apollo= proposta.proposta_apollo, proesso_id= resposta['id'], usuario_criou= 'SUPORTE SISTEMAS', nome_processo= '[FAT] Faturamento de Estoque' ) ) return Resultado(sucesso=True, mensagem=resposta['id']) except Exception as e: logging.error("Erro inesperado ao processar proposta %s: %s", proposta.proposta_apollo, e, exc_info=True) return Resultado(sucesso=False, mensagem=str(e)) # import json # import logging # import os # import requests # from src.models.erro_holmes import ErroHolmes # from src.models.estoque_homes import EstoqueHolmes # from src.models.proposta import Proposta # from src.models.resultado import Resultado # from src.repositories.estoque_repository import EstoqueRepository # from src.utils.utils import extrair_proposta # class HolmesAPI: # def __init__(self): # self.headers = { # "authorization": self._token_usuario(), # "Content-Type": "application/json" # } # def _somente_digitos(self, valor) -> str: # return ''.join(c for c in str(valor or '') if c.isdigit()) # def _token_usuario(self) -> str: # url = "https://app-api.holmesdoc.io/v1/session" # body = {"email": os.getenv('HOLMES_USER'), "password": os.getenv('HOLMES_PASS')} # headers = {"Content-Type": "application/json", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/151.0.0.0 Safari/537.36"} # response = requests.post(url, json=body, headers=headers) # response.raise_for_status() # dados = response.json() # if "token" not in dados: # logging.error( # f"Login Holmes sem token (HTTP {response.status_code}): {str(dados)[:500]}" # ) # raise RuntimeError("Login Holmes não retornou token") # return dados["token"] # def _build_payload_novos(self, proposta: Proposta) -> dict: # start_event = 'StartEvent_1' # campos = [ # ("e88ea290-8ce4-11f1-9f28-e51e49945850", proposta.empresa_holmes), # ("ed2d30f0-8ce4-11f1-9f28-e51e49945850", proposta.tipo_pessoa), # ("f2fe24d0-8ce4-11f1-9f28-e51e49945850", proposta.usado_na_troca), # ("2aafcff0-8cf4-11f1-9f28-e51e49945850", proposta.forma_pagamento), # ("fad87d40-8ce4-11f1-9f28-e51e49945850", proposta.proposta_apollo), # ("fdfd63f0-8ce4-11f1-9f28-e51e49945850", proposta.veiculo), # ("01109760-8ce5-11f1-9f28-e51e49945850", proposta.chassi), # ("04ab7160-8ce5-11f1-9f28-e51e49945850", proposta.des_modelo), # ("1b0974c0-8ce5-11f1-9f28-e51e49945850", proposta.valor_proposta), # ("23914b40-8ce5-11f1-9f28-e51e49945850", proposta.nome), # ("27b419f0-8ce5-11f1-9f28-e51e49945850", self._somente_digitos(proposta.cpfcnpj)), # ("398ac070-8ce5-11f1-9f28-e51e49945850", self._somente_digitos(proposta.celular)), # ("3e7bb490-8ce5-11f1-9f28-e51e49945850", proposta.email), # ("6873d880-9ccc-11f1-b919-f777409ec14c", proposta.vendedor_holmes), # ] # payload = { # "workflow": { # "start_event": start_event, # "property_values": [ # {"id": prop_id, "value": valor} # for prop_id, valor in campos # if valor is not None and str(valor).strip() != '' # ], # "whats": "", # "documents": [], # "test": False # } # } # logging.debug("Payload proposta %s: %s", proposta.proposta_apollo, payload) # return payload # def _build_payload_usados(self, proposta: Proposta) -> dict: # start_event = 'StartEvent_1' # campos = [ # ("e88ea290-8ce4-11f1-9f28-e51e49945850", proposta.empresa_holmes), # ("ed2d30f0-8ce4-11f1-9f28-e51e49945850", proposta.tipo_pessoa), # ("2aafcff0-8cf4-11f1-9f28-e51e49945850", proposta.forma_pagamento), # ("f2fe24d0-8ce4-11f1-9f28-e51e49945850", proposta.usado_na_troca), # ("fad87d40-8ce4-11f1-9f28-e51e49945850", proposta.proposta_apollo), # ("fdfd63f0-8ce4-11f1-9f28-e51e49945850", proposta.veiculo), # ("01109760-8ce5-11f1-9f28-e51e49945850", proposta.chassi), # ("04ab7160-8ce5-11f1-9f28-e51e49945850", proposta.des_modelo), # ("08b38c20-8ce5-11f1-9f28-e51e49945850", proposta.placa), # ("1b0974c0-8ce5-11f1-9f28-e51e49945850", proposta.valor_proposta), # ("23914b40-8ce5-11f1-9f28-e51e49945850", proposta.nome), # ("27b419f0-8ce5-11f1-9f28-e51e49945850", self._somente_digitos(proposta.cpfcnpj)), # ("398ac070-8ce5-11f1-9f28-e51e49945850", self._somente_digitos(proposta.celular)), # ("3e7bb490-8ce5-11f1-9f28-e51e49945850", proposta.email), # ("19c78c10-9d92-11f1-ad38-41765eab56e3", proposta.vendedor_holmes), # ] # payload = { # "workflow": { # "start_event": start_event, # "property_values": [ # {"id": prop_id, "value": valor} # for prop_id, valor in campos # if valor is not None and str(valor).strip() != '' # ], # "whats": "", # "documents": [], # "test": False # } # } # logging.debug("Payload proposta %s: %s", proposta.proposta_apollo, payload) # return payload # def _build_payload_imobilizado(self, proposta: Proposta) -> dict: # start_event = 'StartEvent_1' # campos = [ # ("e88ea290-8ce4-11f1-9f28-e51e49945850", proposta.empresa_holmes), # ("ed2d30f0-8ce4-11f1-9f28-e51e49945850", proposta.tipo_pessoa), # ("f2fe24d0-8ce4-11f1-9f28-e51e49945850", proposta.usado_na_troca), # ("2aafcff0-8cf4-11f1-9f28-e51e49945850", proposta.forma_pagamento), # ("fad87d40-8ce4-11f1-9f28-e51e49945850", proposta.proposta_apollo), # ("fdfd63f0-8ce4-11f1-9f28-e51e49945850", proposta.veiculo), # ("01109760-8ce5-11f1-9f28-e51e49945850", proposta.chassi), # ("04ab7160-8ce5-11f1-9f28-e51e49945850", proposta.des_modelo), # ("08b38c20-8ce5-11f1-9f28-e51e49945850", proposta.placa), # ("1b0974c0-8ce5-11f1-9f28-e51e49945850", proposta.valor_proposta), # ("23914b40-8ce5-11f1-9f28-e51e49945850", proposta.nome), # ("27b419f0-8ce5-11f1-9f28-e51e49945850", self._somente_digitos(proposta.cpfcnpj)), # ("398ac070-8ce5-11f1-9f28-e51e49945850", self._somente_digitos(proposta.celular)), # ("3e7bb490-8ce5-11f1-9f28-e51e49945850", proposta.email), # ("d1b18d20-9d98-11f1-8298-cb4f6a31d606", proposta.vendedor_holmes), # ] # payload = { # "workflow": { # "start_event": start_event, # "property_values": [ # {"id": prop_id, "value": valor} # for prop_id, valor in campos # if valor is not None and str(valor).strip() != '' # ], # "whats": "", # "documents": [], # "test": False # } # } # logging.debug("Payload proposta %s: %s", proposta.proposta_apollo, payload) # return payload # def _build_payload_venda_direta(self, proposta: Proposta) -> dict: # # Esse formulario tem IDs proprios (nao reaproveita os dos outros tres), # # nao tem Placa e traz a Observacao da proposta. # start_event = 'StartEvent_1' # campos = [ # ("37897690-8d03-11f1-9f28-e51e49945850", proposta.empresa_holmes), # ("420c59c0-8d03-11f1-9f28-e51e49945850", proposta.tipo_pessoa), # ("46da1900-8d04-11f1-9f28-e51e49945850", proposta.forma_pagamento), # ("48ee6f80-8d03-11f1-9f28-e51e49945850", proposta.usado_na_troca), # ("53933290-8d03-11f1-9f28-e51e49945850", proposta.proposta_apollo), # ("58d81310-8d03-11f1-9f28-e51e49945850", proposta.veiculo), # ("5b19c5b0-8d03-11f1-9f28-e51e49945850", proposta.chassi), # ("5f92a3a0-8d03-11f1-9f28-e51e49945850", proposta.des_modelo), # ("6b95e540-8d03-11f1-9f28-e51e49945850", proposta.valor_proposta), # ("73c56290-8d03-11f1-9f28-e51e49945850", proposta.nome), # ("79635f90-8d03-11f1-9f28-e51e49945850", self._somente_digitos(proposta.cpfcnpj)), # ("85ea9e40-8d03-11f1-9f28-e51e49945850", self._somente_digitos(proposta.celular)), # ("8f16f220-8d03-11f1-9f28-e51e49945850", proposta.email), # ("cbe61910-a2de-11f1-aff4-4f1f04587741", proposta.vendedor_holmes), # ("e7610290-a2de-11f1-aff4-4f1f04587741", proposta.observacao), # ] # payload = { # "workflow": { # "start_event": start_event, # "property_values": [ # {"id": prop_id, "value": valor} # for prop_id, valor in campos # if valor is not None and str(valor).strip() != '' # ], # "whats": "", # "documents": [], # "test": False # } # } # logging.debug("Payload proposta %s: %s", proposta.proposta_apollo, payload) # return payload # def existe_holmes(self, chassi: str, proposta: str) -> bool: # """Confere se o chassi já está lançado no holmes e caso tenha o mesmo chassi ele bate a proposta # Args: # chassi (str): Chassi do veiculo vendido # proposta (str): Proposta do veiculo # Returns: # bool: True caso existir e False caso não exista no holmes # """ # logging.info("Verificando se chassi %s (proposta %s) já existe no Holmes", chassi, proposta) # url = 'https://app-api.holmesdoc.io/v2/search' # body = { # "query": { # "from": 0, # "size": 50, # "context": "process", # "sort": "updated_at", # "order": "desc", # "groups": [ # { # "match_all": True, # "terms": [ # { # "value": f"{chassi}", # "type": "match_phrase", # "field": "_content" # } # ] # } # ] # }, # "trash": False, # "deleted_by_me": False # } # resposta = requests.post(url, json=body, headers=self.headers) # resposta.raise_for_status() # dados = resposta.json() # if dados['total'] == 0: # logging.info("Chassi %s não encontrado no Holmes", chassi) # return False # docs_validos = [ # doc for doc in dados['docs'] # if doc.get('name') == '[FAT] Faturamento de Estoque' # and doc.get('status') != 'canceled' # ] # if not docs_validos: # logging.info("Chassi %s encontrado mas sem processos válidos (todos cancelados ou de outro template)", chassi) # return False # proposta_holmes = extrair_proposta(docs_validos[0]['identifier']) # if str(proposta_holmes) != str(proposta): # logging.info("Chassi %s encontrado mas proposta diferente (Holmes: %s, Apollo: %s)", chassi, proposta_holmes, proposta) # return False # logging.info("Chassi %s já existe no Holmes com mesma proposta %s", chassi, proposta) # return True # def envia_fat_estoque_usado(self, proposta: Proposta, estoque_repo: EstoqueRepository) -> Resultado: # logging.info("Enviando proposta %s para Holmes (empresa=%s, revenda=%s)", proposta.proposta_apollo, proposta.empresa, proposta.revenda) # url = 'https://app-api.holmesdoc.io/v1/workflows/6a6cc58744c4ba86a63aebc1/start' # payload = self._build_payload_usados(proposta) # logging.debug("Payload montado para proposta %s", proposta.proposta_apollo) # response = requests.post(url, headers=self.headers, data=json.dumps(payload)) # logging.debug("Holmes respondeu com status %s para proposta %s", response.status_code, proposta.proposta_apollo) # try: # if response.status_code != 200: # err_msg = f"Erro ao enviar para Holmes: {response.status_code} - {response.text or ''}" # err_msg = (err_msg[:3900] + "...") if len(err_msg) > 3900 else err_msg # logging.error("Falha ao enviar proposta %s: %s", proposta.proposta_apollo, err_msg) # estoque_repo.insere_erro( # ErroHolmes( # empresa = proposta.empresa, # revenda = proposta.revenda, # proposta_apollo = proposta.proposta_apollo, # motivo_erro= err_msg # ) # ) # return Resultado(sucesso=False, mensagem=err_msg) # else: # resposta = response.json() # logging.info("Proposta %s enviada com sucesso - processo Holmes: %s", proposta.proposta_apollo, resposta['id']) # estoque_repo.insere_estoque( # EstoqueHolmes( # empresa= proposta.empresa, # revenda= proposta.revenda, # proposta_apollo= proposta.proposta_apollo, # proesso_id= resposta['id'], # usuario_criou= 'SUPORTE SISTEMAS', # nome_processo= '[FAT] Faturamento de Estoque' # ) # ) # return Resultado(sucesso=True, mensagem=resposta['id']) # except Exception as e: # logging.error("Erro inesperado ao processar proposta %s: %s", proposta.proposta_apollo, e, exc_info=True) # return Resultado(sucesso=False, mensagem=str(e)) # def envia_fat_estoque_novos(self, proposta: Proposta, estoque_repo: EstoqueRepository) -> Resultado: # logging.info("Enviando proposta %s para Holmes (empresa=%s, revenda=%s)", proposta.proposta_apollo, proposta.empresa, proposta.revenda) # url = 'https://app-api.holmesdoc.io/v1/workflows/6a6cbe67aff519bb6aa4b2d8/start' # payload = self._build_payload_novos(proposta) # logging.debug("Payload montado para proposta %s", proposta.proposta_apollo) # response = requests.post(url, headers=self.headers, data=json.dumps(payload)) # logging.debug("Holmes respondeu com status %s para proposta %s", response.status_code, proposta.proposta_apollo) # try: # if response.status_code != 200: # err_msg = f"Erro ao enviar para Holmes: {response.status_code} - {response.text or ''}" # err_msg = (err_msg[:3900] + "...") if len(err_msg) > 3900 else err_msg # logging.error("Falha ao enviar proposta %s: %s", proposta.proposta_apollo, err_msg) # estoque_repo.insere_erro( # ErroHolmes( # empresa = proposta.empresa, # revenda = proposta.revenda, # proposta_apollo = proposta.proposta_apollo, # motivo_erro= err_msg # ) # ) # return Resultado(sucesso=False, mensagem=err_msg) # else: # resposta = response.json() # logging.info("Proposta %s enviada com sucesso - processo Holmes: %s", proposta.proposta_apollo, resposta['id']) # estoque_repo.insere_estoque( # EstoqueHolmes( # empresa= proposta.empresa, # revenda= proposta.revenda, # proposta_apollo= proposta.proposta_apollo, # proesso_id= resposta['id'], # usuario_criou= 'SUPORTE SISTEMAS', # nome_processo= '[FAT] Faturamento de Estoque' # ) # ) # return Resultado(sucesso=True, mensagem=resposta['id']) # except Exception as e: # logging.error("Erro inesperado ao processar proposta %s: %s", proposta.proposta_apollo, e, exc_info=True) # return Resultado(sucesso=False, mensagem=str(e)) # def envia_fat_estoque_imobilizado(self, proposta: Proposta, estoque_repo: EstoqueRepository) -> Resultado: # logging.info("Enviando proposta %s para Holmes (empresa=%s, revenda=%s)", proposta.proposta_apollo, proposta.empresa, proposta.revenda) # url = 'https://app-api.holmesdoc.io/v1/workflows/6a6cc2a3dbf5173588777520/start' # payload = self._build_payload_imobilizado(proposta) # logging.debug("Payload montado para proposta %s", proposta.proposta_apollo) # response = requests.post(url, headers=self.headers, data=json.dumps(payload)) # logging.debug("Holmes respondeu com status %s para proposta %s", response.status_code, proposta.proposta_apollo) # try: # if response.status_code != 200: # err_msg = f"Erro ao enviar para Holmes: {response.status_code} - {response.text or ''}" # err_msg = (err_msg[:3900] + "...") if len(err_msg) > 3900 else err_msg # logging.error("Falha ao enviar proposta %s: %s", proposta.proposta_apollo, err_msg) # estoque_repo.insere_erro( # ErroHolmes( # empresa = proposta.empresa, # revenda = proposta.revenda, # proposta_apollo = proposta.proposta_apollo, # motivo_erro= err_msg # ) # ) # return Resultado(sucesso=False, mensagem=err_msg) # else: # resposta = response.json() # logging.info("Proposta %s enviada com sucesso - processo Holmes: %s", proposta.proposta_apollo, resposta['id']) # estoque_repo.insere_estoque( # EstoqueHolmes( # empresa= proposta.empresa, # revenda= proposta.revenda, # proposta_apollo= proposta.proposta_apollo, # proesso_id= resposta['id'], # usuario_criou= 'SUPORTE SISTEMAS', # nome_processo= '[FAT] Faturamento de Estoque' # ) # ) # return Resultado(sucesso=True, mensagem=resposta['id']) # except Exception as e: # logging.error("Erro inesperado ao processar proposta %s: %s", proposta.proposta_apollo, e, exc_info=True) # return Resultado(sucesso=False, mensagem=str(e)) # def envia_fat_estoque_venda_direta(self, proposta: Proposta, estoque_repo: EstoqueRepository) -> Resultado: # logging.info("Enviando proposta %s para Holmes (empresa=%s, revenda=%s)", proposta.proposta_apollo, proposta.empresa, proposta.revenda) # url = 'https://app-api.holmesdoc.io/v1/workflows/6a6cd6449341bbc7e45f29cf/start' # payload = self._build_payload_venda_direta(proposta) # logging.debug("Payload montado para proposta %s", proposta.proposta_apollo) # response = requests.post(url, headers=self.headers, data=json.dumps(payload)) # logging.debug("Holmes respondeu com status %s para proposta %s", response.status_code, proposta.proposta_apollo) # try: # if response.status_code != 200: # err_msg = f"Erro ao enviar para Holmes: {response.status_code} - {response.text or ''}" # err_msg = (err_msg[:3900] + "...") if len(err_msg) > 3900 else err_msg # logging.error("Falha ao enviar proposta %s: %s", proposta.proposta_apollo, err_msg) # estoque_repo.insere_erro( # ErroHolmes( # empresa = proposta.empresa, # revenda = proposta.revenda, # proposta_apollo = proposta.proposta_apollo, # motivo_erro= err_msg # ) # ) # return Resultado(sucesso=False, mensagem=err_msg) # else: # resposta = response.json() # logging.info("Proposta %s enviada com sucesso - processo Holmes: %s", proposta.proposta_apollo, resposta['id']) # estoque_repo.insere_estoque( # EstoqueHolmes( # empresa= proposta.empresa, # revenda= proposta.revenda, # proposta_apollo= proposta.proposta_apollo, # proesso_id= resposta['id'], # usuario_criou= 'SUPORTE SISTEMAS', # nome_processo= '[FAT] Faturamento de Estoque' # ) # ) # return Resultado(sucesso=True, mensagem=resposta['id']) # except Exception as e: # logging.error("Erro inesperado ao processar proposta %s: %s", proposta.proposta_apollo, e, exc_info=True) # return Resultado(sucesso=False, mensagem=str(e))