worker-automate-hub 0.5.857__tar.gz → 0.5.892__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (119) hide show
  1. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/PKG-INFO +1 -1
  2. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/pyproject.toml +1 -1
  3. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/api/client.py +6 -6
  4. worker_automate_hub-0.5.892/worker_automate_hub/tasks/jobs/extracao_dados_nielsen.py +504 -0
  5. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/tasks/jobs/fidc_gerar_nosso_numero.py +2 -2
  6. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/tasks/jobs/importacao_extratos_748.py +177 -63
  7. worker_automate_hub-0.5.892/worker_automate_hub/tasks/jobs/inclusao_pedidos_ipiranga.py +217 -0
  8. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/tasks/jobs/inclusao_pedidos_raizen.py +1 -1
  9. worker_automate_hub-0.5.892/worker_automate_hub/tasks/jobs/inclusao_pedidos_vibra.py +327 -0
  10. worker_automate_hub-0.5.892/worker_automate_hub/tasks/jobs/opex_capex.py +1046 -0
  11. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/tasks/task_definitions.py +6 -0
  12. worker_automate_hub-0.5.857/worker_automate_hub/tasks/jobs/inclusao_pedidos_ipiranga.py +0 -5
  13. worker_automate_hub-0.5.857/worker_automate_hub/tasks/jobs/inclusao_pedidos_vibra.py +0 -293
  14. worker_automate_hub-0.5.857/worker_automate_hub/tasks/jobs/opex_capex.py +0 -931
  15. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/README.md +0 -0
  16. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/__init__.py +0 -0
  17. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/api/__init__.py +0 -0
  18. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/api/ahead_service.py +0 -0
  19. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/api/datalake_service.py +0 -0
  20. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/api/helpers/__init__.py +0 -0
  21. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/api/helpers/api_helpers.py +0 -0
  22. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/api/rdp_service.py +0 -0
  23. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/api/rpa_fila_service.py +0 -0
  24. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/api/rpa_historico_service.py +0 -0
  25. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/api/webhook_service.py +0 -0
  26. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/cli.py +0 -0
  27. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/config/__init__.py +0 -0
  28. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/config/settings.py +0 -0
  29. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/config.py +0 -0
  30. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/core/so_manipulation.py +0 -0
  31. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/decorators/__init__.py +0 -0
  32. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/decorators/deprecation.py +0 -0
  33. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/decorators/rate_limit.py +0 -0
  34. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/decorators/repeat.py +0 -0
  35. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/decorators/retry.py +0 -0
  36. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/decorators/singleton.py +0 -0
  37. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/decorators/timeit.py +0 -0
  38. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/models/__init__.py +0 -0
  39. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/models/dao/__init__.py +0 -0
  40. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/models/dao/rpa_configuracao.py +0 -0
  41. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/models/dao/rpa_fila.py +0 -0
  42. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/models/dao/rpa_historico.py +0 -0
  43. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/models/dao/rpa_processo.py +0 -0
  44. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/models/dao/rpa_robo.py +0 -0
  45. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/models/dto/__init__.py +0 -0
  46. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/models/dto/rpa_historico_request_dto.py +0 -0
  47. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/models/dto/rpa_processo_entrada_dto.py +0 -0
  48. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/models/dto/rpa_processo_rdp_dto.py +0 -0
  49. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/models/dto/rpa_sap_dto.py +0 -0
  50. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/models/dto/rpa_sistema_dto.py +0 -0
  51. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/tasks/__init__.py +0 -0
  52. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/tasks/jobs/__init__.py +0 -0
  53. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/tasks/jobs/abertura_livros_fiscais.py +0 -0
  54. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/tasks/jobs/coleta_dje_process.py +0 -0
  55. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/tasks/jobs/conexao_rdp.py +0 -0
  56. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/tasks/jobs/cte_manual.py +0 -0
  57. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/tasks/jobs/cte_xml.py +0 -0
  58. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/tasks/jobs/descartes.py +0 -0
  59. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/tasks/jobs/devolucao_ctf.py +0 -0
  60. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/tasks/jobs/devolucao_ctf_35.py +0 -0
  61. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/tasks/jobs/devolucao_prazo_a_faturar.py +0 -0
  62. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/tasks/jobs/devolucao_produtos.py +0 -0
  63. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/tasks/jobs/ecac_estadual_go.py +0 -0
  64. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/tasks/jobs/ecac_estadual_main.py +0 -0
  65. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/tasks/jobs/ecac_estadual_mt.py +0 -0
  66. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/tasks/jobs/ecac_estadual_sc.py +0 -0
  67. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/tasks/jobs/ecac_estadual_sp.py +0 -0
  68. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/tasks/jobs/ecac_federal.py +0 -0
  69. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/tasks/jobs/entrada_cte_1353.py +0 -0
  70. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/tasks/jobs/entrada_cte_333.py +0 -0
  71. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/tasks/jobs/entrada_de_notas_15.py +0 -0
  72. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/tasks/jobs/entrada_de_notas_16.py +0 -0
  73. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/tasks/jobs/entrada_de_notas_207.py +0 -0
  74. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/tasks/jobs/entrada_de_notas_22.py +0 -0
  75. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/tasks/jobs/entrada_de_notas_32.py +0 -0
  76. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/tasks/jobs/entrada_de_notas_33.py +0 -0
  77. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/tasks/jobs/entrada_de_notas_34.py +0 -0
  78. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/tasks/jobs/entrada_de_notas_36.py +0 -0
  79. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/tasks/jobs/entrada_de_notas_37.py +0 -0
  80. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/tasks/jobs/entrada_de_notas_39.py +0 -0
  81. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/tasks/jobs/entrada_de_notas_500.py +0 -0
  82. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/tasks/jobs/entrada_de_notas_503.py +0 -0
  83. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/tasks/jobs/entrada_de_notas_505.py +0 -0
  84. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/tasks/jobs/entrada_de_notas_7139.py +0 -0
  85. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/tasks/jobs/entrada_de_notas_9.py +0 -0
  86. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/tasks/jobs/entrada_de_notas_9000.py +0 -0
  87. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/tasks/jobs/exemplo_processo.py +0 -0
  88. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/tasks/jobs/extracao_fechamento_contabil.py +0 -0
  89. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/tasks/jobs/extracao_fechamento_emsys.py +0 -0
  90. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/tasks/jobs/extracao_saldo_estoque.py +0 -0
  91. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/tasks/jobs/extracao_saldo_estoque_fiscal.py +0 -0
  92. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/tasks/jobs/fechar_conexao_rdp.py +0 -0
  93. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/tasks/jobs/fidc_exportacao_docs_portal_b2b.py +0 -0
  94. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/tasks/jobs/fidc_remessa_cobranca_cnab240.py +0 -0
  95. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/tasks/jobs/fidc_retorno_cobranca.py +0 -0
  96. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/tasks/jobs/geracao_aprovacao_pedidos.py +0 -0
  97. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/tasks/jobs/geracao_aprovacao_pedidos_novo.py +0 -0
  98. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/tasks/jobs/geracao_balancetes_filial.py +0 -0
  99. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/tasks/jobs/importacao_extratos.py +0 -0
  100. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/tasks/jobs/integracao_contabil.py +0 -0
  101. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/tasks/jobs/integracao_contabil_generica.py +0 -0
  102. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/tasks/jobs/lancamento_pis_cofins.py +0 -0
  103. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/tasks/jobs/lancamento_rateio.py +0 -0
  104. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/tasks/jobs/login_emsys.py +0 -0
  105. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/tasks/jobs/login_emsys_versao_especifica.py +0 -0
  106. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/tasks/jobs/notas_faturamento_sap.py +0 -0
  107. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/tasks/jobs/playground.py +0 -0
  108. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/tasks/jobs/sped_fiscal.py +0 -0
  109. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/tasks/jobs/transferencias.py +0 -0
  110. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/tasks/task_executor.py +0 -0
  111. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/utils/__init__.py +0 -0
  112. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/utils/env.py +0 -0
  113. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/utils/get_creds_gworkspace.py +0 -0
  114. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/utils/logger.py +0 -0
  115. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/utils/toast.py +0 -0
  116. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/utils/updater.py +0 -0
  117. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/utils/util.py +0 -0
  118. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/utils/utils_nfe_entrada.py +0 -0
  119. {worker_automate_hub-0.5.857 → worker_automate_hub-0.5.892}/worker_automate_hub/worker.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: worker-automate-hub
3
- Version: 0.5.857
3
+ Version: 0.5.892
4
4
  Summary: Worker Automate HUB é uma aplicação para automatizar rotinas de RPA nos ambientes Argenta.
5
5
  Author: Joel Paim
6
6
  Requires-Python: >=3.12,<4.0
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "worker-automate-hub"
3
- version = "0.5.857"
3
+ version = "0.5.892"
4
4
  description = "Worker Automate HUB é uma aplicação para automatizar rotinas de RPA nos ambientes Argenta."
5
5
  authors = ["Joel Paim"]
6
6
  readme = "README.md"
@@ -622,7 +622,7 @@ async def get_dados_nf_emsys(
622
622
  chave: Optional[int] = None,
623
623
  numero_nota: Optional[int] = None,
624
624
  serie_nota: Optional[int] = None,
625
- filial_nota: Optional[int] = None
625
+ fornecedor: Optional[int] = None
626
626
  ):
627
627
  """
628
628
  Consulta a NF no EMSYS (ahead-nota) e retorna os campos essenciais:
@@ -632,7 +632,7 @@ async def get_dados_nf_emsys(
632
632
  chave (int, opcional): Chave de acesso da NF.
633
633
  numero_nota (int, opcional): Número da NF.
634
634
  serie_nota (int, opcional): Série da NF (obrigatória se numero_nota for informado).
635
- filial_nota (int, opcional): Filial da NF (obrigatória se numero_nota for informado).
635
+ fornecedor (int, opcional): Filial da NF (obrigatória se numero_nota for informado).
636
636
 
637
637
  Returns:
638
638
  list[dict]: Lista de notas no formato esperado.
@@ -649,14 +649,14 @@ async def get_dados_nf_emsys(
649
649
 
650
650
  # Caso 2: veio numero_nota → exige serie e filial
651
651
  elif numero_nota is not None:
652
- if serie_nota is None or filial_nota is None:
653
- raise ValueError("Para buscar por número da nota é obrigatório informar também 'serie_nota' e 'filial_nota'.")
652
+ if serie_nota is None or fornecedor is None:
653
+ raise ValueError("Para buscar por número da nota é obrigatório informar também 'serie_nota' e 'fornecedor'.")
654
654
  params["numeroNfe"] = numero_nota
655
655
  params["serieNfe"] = serie_nota
656
- params["empresaCodigo"] = filial_nota
656
+ params["fornecedorCnpj"] = fornecedor
657
657
 
658
658
  else:
659
- raise ValueError("É necessário informar 'chave' ou ('numero_nota' + 'serie_nota' + 'filial_nota').")
659
+ raise ValueError("É necessário informar 'chave' ou ('numero_nota' + 'serie_nota' + 'fornecedor').")
660
660
 
661
661
  headers_basic = {"Authorization": f"Basic {env_config['API_AUTHORIZATION']}"}
662
662
 
@@ -0,0 +1,504 @@
1
+ # IMPORT SELENIUM
2
+ import os
3
+ import sys
4
+ import time
5
+ import json
6
+ import asyncio
7
+ import shutil
8
+ from typing import List
9
+ from datetime import datetime
10
+ from rich.console import Console
11
+
12
+
13
+ from selenium import webdriver
14
+ from selenium.webdriver.common.by import By
15
+ from selenium.webdriver.remote.webelement import WebElement
16
+ from selenium.webdriver.support.ui import WebDriverWait
17
+ from selenium.webdriver.support import expected_conditions as EC
18
+ from selenium.webdriver.chrome.service import Service
19
+ from selenium.webdriver.chrome.options import Options
20
+ from selenium.common.exceptions import TimeoutException
21
+ from webdriver_manager.chrome import ChromeDriverManager
22
+ from os import name
23
+
24
+ # from selenium.webdriver.support.ui import WebDriverWait
25
+ from selenium.webdriver.support.wait import WebDriverWait
26
+ from selenium.webdriver.chrome.webdriver import WebDriver
27
+
28
+ ROOT_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..", ".."))
29
+ sys.path.append(ROOT_PATH)
30
+
31
+ from worker_automate_hub.api.datalake_service import send_file_to_datalake
32
+ from worker_automate_hub.api.client import get_config_by_name
33
+ from worker_automate_hub.models.dto.rpa_historico_request_dto import (
34
+ RpaHistoricoStatusEnum,
35
+ RpaRetornoProcessoDTO,
36
+ RpaTagDTO,
37
+ RpaTagEnum,
38
+ )
39
+ from worker_automate_hub.models.dto.rpa_processo_entrada_dto import (
40
+ RpaProcessoEntradaDTO,
41
+ )
42
+
43
+ from worker_automate_hub.utils.util import (
44
+ kill_all_emsys,
45
+ )
46
+ USERNAME = os.environ.get("USERNAME")
47
+ console = Console()
48
+
49
+ HISTORICO_ID = "e8ca47cf-c49b-437c-9028-50bcfa5fe021"
50
+
51
+ # Diretório/bucket no datalake onde os arquivos serão enviados
52
+ DATALAKE_DIRECTORY = "nielsen_arquivos/raw"
53
+
54
+ # Funcões Selenium
55
+
56
+
57
+ def aguardar_elemento_ser_clicavel_xpath(
58
+ driver: WebDriver, xpath: str, tempo: int
59
+ ) -> bool:
60
+ aguardar = WebDriverWait(driver, tempo)
61
+ return aguardar.until(EC.element_to_be_clickable((By.XPATH, xpath)))
62
+
63
+
64
+ def inserir_texto_por_letra_xpath(driver: WebDriver, xpath: str, texto: str):
65
+ for letter in texto:
66
+ driver.find_element(By.XPATH, xpath).send_keys(letter)
67
+ time.sleep(0.1)
68
+
69
+
70
+ def inserir_texto_por_xpath(driver: WebDriver, xpath: str, texto: str):
71
+ driver.find_element(By.XPATH, xpath).send_keys(texto)
72
+
73
+
74
+ def clicar_elemento_por_xpath(driver: WebDriver, xpath: str) -> None:
75
+ driver.find_element(By.XPATH, xpath).click()
76
+
77
+
78
+ def busca_lista_elementos_por_xpath(driver: WebDriver, xpath: str) -> List[WebElement]:
79
+ return driver.find_elements(By.XPATH, xpath)
80
+
81
+
82
+ def limpar_pasta_downloads(caminho: str, remover_pastas: bool = False):
83
+ """
84
+ Limpa a pasta de downloads utilizada pelo robô.
85
+
86
+ Args:
87
+ caminho (str): Caminho da pasta a ser limpa.
88
+ remover_pastas (bool): Se True, remove também subpastas.
89
+ """
90
+ if not os.path.exists(caminho):
91
+ console.print(f"Pasta não existe: {caminho}", style="yellow")
92
+ return
93
+
94
+ try:
95
+ itens = os.listdir(caminho)
96
+
97
+ if not itens:
98
+ console.print("Pasta já estava vazia.", style="green")
99
+ return
100
+
101
+ for item in itens:
102
+ item_path = os.path.join(caminho, item)
103
+
104
+ try:
105
+ # Remover arquivos
106
+ if os.path.isfile(item_path):
107
+ os.remove(item_path)
108
+ console.print(f"Arquivo removido: {item_path}", style="green")
109
+
110
+ # Remover pastas (opcional)
111
+ elif remover_pastas and os.path.isdir(item_path):
112
+ shutil.rmtree(item_path, ignore_errors=True)
113
+ console.print(f"Pasta removida: {item_path}", style="green")
114
+
115
+ except Exception as e:
116
+ console.print(
117
+ f"Não foi possível remover {item_path}: {e}",
118
+ style="bold red",
119
+ )
120
+
121
+ console.print("Limpeza concluída!", style="bold green")
122
+
123
+ except Exception as e:
124
+ console.print(f"Erro ao limpar pasta: {e}", style="bold red")
125
+
126
+
127
+ class ExtracaoDados:
128
+ def __init__(self, driver: webdriver.Chrome):
129
+ self.driver = driver
130
+ self.caminho_downloads = rf"C:\Users\{USERNAME}\Downloads"
131
+ self.handles = []
132
+
133
+ async def limpar_downloads(self):
134
+ limpar_pasta_downloads(self.caminho_downloads, remover_pastas=False)
135
+
136
+ async def abrir_site(self):
137
+ await asyncio.sleep(2)
138
+ try:
139
+ console.print(
140
+ "Iniciando navegador e acessando site da Nielsen...", style="cyan"
141
+ )
142
+ self.driver.get("https://web.na-mft.nielseniq.com/cfcc/bclient/index.jsp#/")
143
+ except Exception as e:
144
+ console.print(f"Erro ao abrir o site: {e}", style="bold red")
145
+ raise
146
+
147
+ # Lê credenciais via API usando RpaConfiguracao.conConfiguracao (JSON)
148
+ async def load_config(self):
149
+ try:
150
+ config = await get_config_by_name("nielsen_credenciais")
151
+
152
+ if config is None:
153
+ raise Exception(
154
+ "get_config_by_name retornou None para 'nielsen_credenciais'."
155
+ )
156
+
157
+ # conConfiguracao é onde fica o conteúdo da configuração
158
+ raw_valor = getattr(config, "conConfiguracao", None)
159
+ if raw_valor is None:
160
+ raise Exception(
161
+ "Objeto RpaConfiguracao não possui conteúdo em 'conConfiguracao'. "
162
+ f"Atributos disponíveis: {dir(config)}"
163
+ )
164
+
165
+ # Se for string JSON, fazer parse
166
+ if isinstance(raw_valor, str):
167
+ try:
168
+ valor_json = json.loads(raw_valor)
169
+ except Exception as e_json:
170
+ raise Exception(
171
+ f"Falha ao fazer json.loads em conConfiguracao: {e_json}. "
172
+ f"valor bruto: {raw_valor}"
173
+ )
174
+ # Se já vier como dict
175
+ elif isinstance(raw_valor, dict):
176
+ valor_json = raw_valor
177
+ else:
178
+ raise Exception(
179
+ f"Tipo inesperado em conConfiguracao: {type(raw_valor)}. "
180
+ "Esperado str (JSON) ou dict."
181
+ )
182
+
183
+ username = valor_json.get("usuario")
184
+ password = valor_json.get("senha")
185
+
186
+ if not username or not password:
187
+ raise Exception(
188
+ "Usuário ou senha não encontrados no JSON da configuração. "
189
+ f"JSON: {valor_json}"
190
+ )
191
+
192
+ return username, password
193
+
194
+ except Exception as e:
195
+ console.print(
196
+ f"Erro ao obter credenciais via get_config_by_name: {e}",
197
+ style="bold red",
198
+ )
199
+ raise
200
+
201
+ async def clicar_diretorio_principal(self, nome_diretorio: str):
202
+ """
203
+ Clica no diretório principal pelo nome, tentando vários seletores
204
+ para não quebrar com mudanças pequenas de HTML.
205
+ """
206
+
207
+ # Possíveis XPaths para localizar o item
208
+ xpaths_possiveis = [
209
+ # 1) span com classe 'file' e texto exato
210
+ f"//span[contains(@class, 'file') and normalize-space(text())='{nome_diretorio}']",
211
+
212
+ # 2) elemento com title igual ao nome (span, a, td, etc.)
213
+ f"//*[@title='{nome_diretorio}' and (self::span or self::a or self::td)]",
214
+
215
+ # 3) tr que tenha aria-label contendo o nome
216
+ f"//tr[contains(@aria-label, '{nome_diretorio}')]",
217
+
218
+ # 4) Qualquer elemento com texto visível igual ao nome
219
+ f"//*[normalize-space(text())='{nome_diretorio}']",
220
+ ]
221
+
222
+ elemento_encontrado = False
223
+ ultimo_erro = None
224
+
225
+ for xpath in xpaths_possiveis:
226
+ try:
227
+ print(f"Tentando localizar diretório com XPath: {xpath}")
228
+ aguardar_elemento_ser_clicavel_xpath(self.driver, xpath, 20)
229
+ clicar_elemento_por_xpath(self.driver, xpath)
230
+ print(f"Diretório '{nome_diretorio}' clicado com sucesso usando XPath: {xpath}.")
231
+ elemento_encontrado = True
232
+ break
233
+ except Exception as e:
234
+ print(f"Não encontrado/clicável com esse XPath. Erro: {e}")
235
+ ultimo_erro = e
236
+
237
+ if not elemento_encontrado:
238
+ raise RuntimeError(
239
+ f"Não foi possível clicar no diretório '{nome_diretorio}' "
240
+ f"com nenhum dos seletores. Último erro: {ultimo_erro}"
241
+ )
242
+
243
+ async def clicar_ultima_pasta(self, timeout: int = 20):
244
+
245
+ wait = WebDriverWait(self.driver, timeout)
246
+
247
+ # 1) Esperar o tbody da tabela ficar presente
248
+ try:
249
+ tbody = wait.until(
250
+ EC.presence_of_element_located(
251
+ # tabela de listagem de arquivos/pastas
252
+ (By.CSS_SELECTOR, "table.cursor-pointer tbody, table.w-full.cursor-pointer.table-auto tbody")
253
+ )
254
+ )
255
+ except TimeoutException:
256
+ raise RuntimeError("Tabela de transfers não encontrada na página.")
257
+
258
+ # 2) Pegar todas as linhas clicáveis
259
+ # No HTML do TIBCO cada linha tem tabindex="0" e aria-label com o nome
260
+ rows = tbody.find_elements(By.CSS_SELECTOR, "tr[tabindex='0'][aria-label]")
261
+
262
+ # Filtra apenas as visíveis (caso tenha linha escondida)
263
+ rows = [r for r in rows if r.is_displayed()]
264
+
265
+ if not rows:
266
+ raise RuntimeError("Nenhuma linha clicável encontrada na tabela.")
267
+
268
+ # 3) Última linha da lista (mais recente)
269
+ last_row = rows[-1]
270
+ print("Última linha encontrada com aria-label:",
271
+ last_row.get_attribute("aria-label"))
272
+
273
+ # 4) Dentro da linha, tentamos clicar no elemento mais específico
274
+ target = None
275
+ try:
276
+ # span com classe 'file' (texto do nome)
277
+ target = last_row.find_element(By.CSS_SELECTOR, "span.file")
278
+ except Exception:
279
+ # fallback: qualquer span da primeira coluna de nome
280
+ try:
281
+ target = last_row.find_element(By.CSS_SELECTOR, "td span")
282
+ except Exception:
283
+ # fallback final: a própria <tr>
284
+ target = last_row
285
+
286
+ # 5) Garantir que o elemento está visível na tela
287
+ self.driver.execute_script(
288
+ "arguments[0].scrollIntoView({block: 'center'});", target
289
+ )
290
+
291
+ # 6) Esperar ficar clicável e clicar
292
+ try:
293
+ wait.until(EC.element_to_be_clickable(target))
294
+ except TimeoutException:
295
+ # se não ficar "clicável" oficialmente, ainda tentamos via JS
296
+ print("⚠️ Elemento não ficou clicável pelo EC, tentando mesmo assim...")
297
+
298
+ try:
299
+ target.click()
300
+ except Exception:
301
+ # fallback robusto: clique via JavaScript
302
+ self.driver.execute_script("arguments[0].click();", target)
303
+
304
+ print("Última pasta/arquivo clicado com sucesso!")
305
+
306
+
307
+
308
+ async def login_e_baixar(self):
309
+ # limpa downloads antes de começar
310
+ await self.limpar_downloads()
311
+
312
+ # pega credenciais via API (async)
313
+ username, password = await self.load_config()
314
+
315
+ console.print("Realizando login na NielsenIQ...", style="cyan")
316
+
317
+ # Inserir usuário
318
+ xpath = "//input[@id='userid']"
319
+ aguardar_elemento_ser_clicavel_xpath(self.driver, xpath, 30)
320
+ inserir_texto_por_letra_xpath(self.driver, xpath, username)
321
+
322
+ # Inserir senha
323
+ xpath = "//input[@id='password']"
324
+ inserir_texto_por_letra_xpath(self.driver, xpath, password)
325
+
326
+ # Clicar em OK
327
+ xpath = "//input[@id='button']"
328
+ clicar_elemento_por_xpath(self.driver, xpath)
329
+
330
+ time.sleep(2)
331
+
332
+ # Clicar no diretório principal LA_BR_REDE_SIM_DO_SUL
333
+ await self.clicar_diretorio_principal("LA_BR_REDE_SIM_DO_SUL")
334
+
335
+
336
+ await asyncio.sleep(5)
337
+
338
+ # ====== CLICAR NA PASTA COM O ÚLTIMO MÊS ======
339
+ await self.clicar_ultima_pasta()
340
+
341
+ await asyncio.sleep(5)
342
+
343
+ # ====== BAIXAR OS ARQUIVOS DENTRO DA PASTA ======
344
+
345
+ # Localiza as linhas de arquivo na tabela atual (TIBCO MFT)
346
+ xpath_linhas_arquivos = (
347
+ "//table[contains(@class,'cursor-pointer') and "
348
+ "contains(@class,'table-auto')]/tbody/tr[@tabindex='0']"
349
+ )
350
+
351
+ # Aguarda até 20 segundos pelo menos 1 linha da tabela aparecer
352
+ WebDriverWait(self.driver, 20).until(
353
+ EC.presence_of_element_located((By.XPATH, xpath_linhas_arquivos))
354
+ )
355
+
356
+ linhas_arquivos = busca_lista_elementos_por_xpath(
357
+ self.driver, xpath_linhas_arquivos
358
+ )
359
+
360
+ qtd_arquivos = len(linhas_arquivos)
361
+ console.print(
362
+ f"Total de linhas (arquivos visíveis): {qtd_arquivos}", style="cyan"
363
+ )
364
+
365
+ # Arquivos já existentes na pasta de download (baseline)
366
+ conhecidos = set(os.listdir(self.caminho_downloads))
367
+
368
+ for r in range(1, qtd_arquivos + 1):
369
+ # Linha r
370
+ xpath_linha = f"{xpath_linhas_arquivos}[{r}]"
371
+
372
+ # Coluna Name: span com classe 'file' (link do arquivo)
373
+ xpath_baixar = rf"{xpath_linha}//span[contains(@class, 'file')]"
374
+ clicar_elemento_por_xpath(self.driver, xpath_baixar)
375
+
376
+ await asyncio.sleep(1)
377
+
378
+ # Esperar o download completar (sem .crdownload/.tmp)
379
+ timeout_segundos = 180
380
+ inicio = time.time()
381
+ novos_arquivos = set()
382
+
383
+ while time.time() - inicio < timeout_segundos:
384
+ arquivos_atual = [
385
+ f
386
+ for f in os.listdir(self.caminho_downloads)
387
+ if not f.endswith(".crdownload") and not f.endswith(".tmp")
388
+ ]
389
+ novos = set(arquivos_atual) - conhecidos
390
+ if novos:
391
+ novos_arquivos = novos
392
+ conhecidos.update(novos)
393
+ break
394
+ await asyncio.sleep(1)
395
+
396
+ if not novos_arquivos:
397
+ console.print(
398
+ "Nenhum arquivo novo foi baixado dentro do tempo limite.",
399
+ style="bold red",
400
+ )
401
+ continue
402
+
403
+ for arquivo_baixado in sorted(novos_arquivos):
404
+ caminho_arquivo = os.path.join(self.caminho_downloads, arquivo_baixado)
405
+ console.print(f"Arquivo baixado: {caminho_arquivo}", style="bold green")
406
+
407
+ try:
408
+ with open(caminho_arquivo, "rb") as file:
409
+ file_bytes = file.read()
410
+
411
+ nome_arquivo = arquivo_baixado
412
+ ext = "doc" # tipo lógico esperado pelo datalake
413
+
414
+ await send_file_to_datalake(
415
+ directory=DATALAKE_DIRECTORY,
416
+ file=file_bytes,
417
+ filename=nome_arquivo,
418
+ file_extension=ext,
419
+ )
420
+
421
+ os.remove(caminho_arquivo)
422
+ console.print(
423
+ f"Arquivo {nome_arquivo} enviado ao datalake e removido da pasta de download.",
424
+ style="bold green",
425
+ )
426
+
427
+ except Exception as e:
428
+ result = (
429
+ f"Arquivo baixado com sucesso, porém erro ao enviar para o datalake: {e} "
430
+ f"- Arquivo mantido em {caminho_arquivo}"
431
+ )
432
+ console.print(result, style="bold red")
433
+
434
+
435
+ async def extracao_dados_nielsen(task: RpaProcessoEntradaDTO) -> RpaRetornoProcessoDTO:
436
+ """
437
+ Função principal para ser chamada pelo worker.
438
+ """
439
+ console.print("Iniciando processo de extração Nielsen...", style="bold cyan")
440
+ driver = None
441
+ await kill_all_emsys()
442
+ try:
443
+ service = Service(ChromeDriverManager().install())
444
+
445
+ # === CONFIG PARA REMOVER POPUPS ===
446
+ chrome_options = Options()
447
+ chrome_prefs = {
448
+ "profile.default_content_setting_values.notifications": 2, # bloqueia notificações
449
+ "profile.default_content_setting_values.automatic_downloads": 1, # permite múltiplos downloads
450
+ "download.prompt_for_download": False, # não perguntar onde salvar
451
+ "download.directory_upgrade": True,
452
+ }
453
+ chrome_options.add_experimental_option("prefs", chrome_prefs)
454
+ chrome_options.add_argument("--disable-popup-blocking") # evita popups gerais
455
+ chrome_options.add_argument("--no-first-run")
456
+ chrome_options.add_argument("--no-default-browser-check")
457
+ chrome_options.add_argument("--disable-notifications")
458
+ chrome_options.add_argument("--disable-gpu")
459
+ chrome_options.add_argument("--disable-software-rasterizer")
460
+ chrome_options.add_argument("--disable-features=VizDisplayCompositor")
461
+ chrome_options.add_argument("--disable-dev-shm-usage")
462
+
463
+ driver = webdriver.Chrome(service=service, options=chrome_options)
464
+ driver.maximize_window()
465
+ console.print("Driver Chrome inicializado e maximizado.", style="green")
466
+
467
+ extracao = ExtracaoDados(driver)
468
+ await extracao.abrir_site()
469
+ await extracao.login_e_baixar()
470
+
471
+ # Fecha o driver com segurança
472
+ if driver:
473
+ try:
474
+ driver.quit()
475
+ driver = None
476
+ console.print("Driver fechado com sucesso.", style="green")
477
+ except Exception as e:
478
+ console.print(f"Erro ao fechar o driver: {e}", style="yellow")
479
+
480
+ console.print(
481
+ "Processo de extração Nielsen finalizado com sucesso.",
482
+ style="bold green",
483
+ )
484
+ return RpaRetornoProcessoDTO(
485
+ sucesso=True,
486
+ retorno="Processo de extração Nielsen finalizado com sucesso.",
487
+ status=RpaHistoricoStatusEnum.Sucesso,
488
+ )
489
+
490
+ except Exception as ex:
491
+ console.print(f"Erro na automação Nielsen: {ex}", style="bold red")
492
+ if driver:
493
+ try:
494
+ driver.quit()
495
+ except Exception:
496
+ pass
497
+
498
+ return RpaRetornoProcessoDTO(
499
+ sucesso=False,
500
+ retorno=f"Erro na automação Nielsen: {ex}",
501
+ status=RpaHistoricoStatusEnum.Falha,
502
+ tags=[RpaTagDTO(descricao=RpaTagEnum.Tecnico)],
503
+ )
504
+
@@ -210,7 +210,7 @@ async def gerar_nosso_numero(task: RpaProcessoEntradaDTO) -> RpaRetornoProcessoD
210
210
  return RpaRetornoProcessoDTO(
211
211
  sucesso=False, retorno=log_msg, status=RpaHistoricoStatusEnum.Falha, tags=[RpaTagDTO(descricao=RpaTagEnum.Tecnico)]
212
212
  )
213
-
213
+ await worker_sleep(60)
214
214
  app = Application().connect(title="Seleciona Cobrança Bancária")
215
215
  main_window = app["Seleciona Cobrança Bancária"]
216
216
  code = main_window.child_window(class_name="TDBIEditCode", found_index=0)
@@ -226,7 +226,7 @@ async def gerar_nosso_numero(task: RpaProcessoEntradaDTO) -> RpaRetornoProcessoD
226
226
  button_ok.click()
227
227
  pyautogui.click(855, 740)
228
228
 
229
- await worker_sleep(80)
229
+ await worker_sleep(120)
230
230
  boleto_argenta = None
231
231
  max_trys = 5
232
232
  trys = 0