worker-automate-hub 0.5.760__tar.gz → 0.5.762__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 (106) hide show
  1. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/PKG-INFO +1 -1
  2. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/pyproject.toml +1 -1
  3. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/tasks/jobs/extracao_saldo_estoque.py +119 -28
  4. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/tasks/jobs/extracao_saldo_estoque_fiscal.py +152 -87
  5. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/README.md +0 -0
  6. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/__init__.py +0 -0
  7. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/api/__init__.py +0 -0
  8. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/api/ahead_service.py +0 -0
  9. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/api/client.py +0 -0
  10. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/api/datalake_service.py +0 -0
  11. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/api/helpers/__init__.py +0 -0
  12. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/api/helpers/api_helpers.py +0 -0
  13. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/api/rdp_service.py +0 -0
  14. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/api/rpa_fila_service.py +0 -0
  15. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/api/rpa_historico_service.py +0 -0
  16. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/api/webhook_service.py +0 -0
  17. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/cli.py +0 -0
  18. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/config/__init__.py +0 -0
  19. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/config/settings.py +0 -0
  20. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/config.py +0 -0
  21. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/core/so_manipulation.py +0 -0
  22. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/decorators/__init__.py +0 -0
  23. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/decorators/deprecation.py +0 -0
  24. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/decorators/rate_limit.py +0 -0
  25. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/decorators/repeat.py +0 -0
  26. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/decorators/retry.py +0 -0
  27. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/decorators/singleton.py +0 -0
  28. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/decorators/timeit.py +0 -0
  29. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/models/__init__.py +0 -0
  30. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/models/dao/__init__.py +0 -0
  31. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/models/dao/rpa_configuracao.py +0 -0
  32. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/models/dao/rpa_fila.py +0 -0
  33. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/models/dao/rpa_historico.py +0 -0
  34. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/models/dao/rpa_processo.py +0 -0
  35. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/models/dao/rpa_robo.py +0 -0
  36. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/models/dto/__init__.py +0 -0
  37. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/models/dto/rpa_historico_request_dto.py +0 -0
  38. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/models/dto/rpa_processo_entrada_dto.py +0 -0
  39. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/models/dto/rpa_processo_rdp_dto.py +0 -0
  40. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/models/dto/rpa_sap_dto.py +0 -0
  41. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/models/dto/rpa_sistema_dto.py +0 -0
  42. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/tasks/__init__.py +0 -0
  43. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/tasks/jobs/__init__.py +0 -0
  44. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/tasks/jobs/abertura_livros_fiscais.py +0 -0
  45. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/tasks/jobs/coleta_dje_process.py +0 -0
  46. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/tasks/jobs/conexao_rdp.py +0 -0
  47. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/tasks/jobs/cte_manual.py +0 -0
  48. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/tasks/jobs/cte_xml.py +0 -0
  49. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/tasks/jobs/descartes.py +0 -0
  50. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/tasks/jobs/devolucao_ctf.py +0 -0
  51. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/tasks/jobs/devolucao_ctf_35.py +0 -0
  52. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/tasks/jobs/devolucao_prazo_a_faturar.py +0 -0
  53. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/tasks/jobs/ecac_estadual_go.py +0 -0
  54. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/tasks/jobs/ecac_estadual_main.py +0 -0
  55. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/tasks/jobs/ecac_estadual_mt.py +0 -0
  56. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/tasks/jobs/ecac_estadual_sc.py +0 -0
  57. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/tasks/jobs/ecac_estadual_sp.py +0 -0
  58. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/tasks/jobs/ecac_federal.py +0 -0
  59. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/tasks/jobs/entrada_cte_1353.py +0 -0
  60. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/tasks/jobs/entrada_cte_333.py +0 -0
  61. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/tasks/jobs/entrada_de_notas_15.py +0 -0
  62. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/tasks/jobs/entrada_de_notas_16.py +0 -0
  63. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/tasks/jobs/entrada_de_notas_207.py +0 -0
  64. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/tasks/jobs/entrada_de_notas_32.py +0 -0
  65. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/tasks/jobs/entrada_de_notas_33.py +0 -0
  66. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/tasks/jobs/entrada_de_notas_34.py +0 -0
  67. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/tasks/jobs/entrada_de_notas_36.py +0 -0
  68. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/tasks/jobs/entrada_de_notas_39.py +0 -0
  69. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/tasks/jobs/entrada_de_notas_500.py +0 -0
  70. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/tasks/jobs/entrada_de_notas_503.py +0 -0
  71. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/tasks/jobs/entrada_de_notas_505.py +0 -0
  72. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/tasks/jobs/entrada_de_notas_7139.py +0 -0
  73. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/tasks/jobs/entrada_de_notas_9.py +0 -0
  74. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/tasks/jobs/entrada_de_notas_9000.py +0 -0
  75. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/tasks/jobs/exemplo_processo.py +0 -0
  76. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/tasks/jobs/extracao_fechamento_contabil.py +0 -0
  77. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/tasks/jobs/extracao_fechamento_emsys.py +0 -0
  78. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/tasks/jobs/fechar_conexao_rdp.py +0 -0
  79. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/tasks/jobs/fidc_exportacao_docs_portal_b2b.py +0 -0
  80. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/tasks/jobs/fidc_gerar_nosso_numero.py +0 -0
  81. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/tasks/jobs/fidc_remessa_cobranca_cnab240.py +0 -0
  82. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/tasks/jobs/fidc_retorno_cobranca.py +0 -0
  83. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/tasks/jobs/geracao_aprovacao_pedidos.py +0 -0
  84. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/tasks/jobs/geracao_aprovacao_pedidos_novo.py +0 -0
  85. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/tasks/jobs/integracao_contabil.py +0 -0
  86. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/tasks/jobs/integracao_contabil_generica.py +0 -0
  87. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/tasks/jobs/lancamento_pis_cofins.py +0 -0
  88. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/tasks/jobs/lancamento_rateio.py +0 -0
  89. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/tasks/jobs/login_emsys.py +0 -0
  90. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/tasks/jobs/login_emsys_versao_especifica.py +0 -0
  91. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/tasks/jobs/notas_faturamento_sap.py +0 -0
  92. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/tasks/jobs/opex_capex.py +0 -0
  93. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/tasks/jobs/playground.py +0 -0
  94. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/tasks/jobs/sped_fiscal.py +0 -0
  95. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/tasks/jobs/transferencias.py +0 -0
  96. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/tasks/task_definitions.py +0 -0
  97. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/tasks/task_executor.py +0 -0
  98. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/utils/__init__.py +0 -0
  99. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/utils/env.py +0 -0
  100. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/utils/get_creds_gworkspace.py +0 -0
  101. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/utils/logger.py +0 -0
  102. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/utils/toast.py +0 -0
  103. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/utils/updater.py +0 -0
  104. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/utils/util.py +0 -0
  105. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/utils/utils_nfe_entrada.py +0 -0
  106. {worker_automate_hub-0.5.760 → worker_automate_hub-0.5.762}/worker_automate_hub/worker.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: worker-automate-hub
3
- Version: 0.5.760
3
+ Version: 0.5.762
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.760"
3
+ version = "0.5.762"
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"
@@ -117,10 +117,11 @@ async def extracao_saldo_estoque(task: RpaProcessoEntradaDTO):
117
117
  while tentativa <= max_tentativas and not sucesso:
118
118
  console.print(f"Tentativa {tentativa} de {max_tentativas}", style="bold cyan")
119
119
 
120
+ # 1) Abrir o picker de formatos pelo botão (imagem)
120
121
  console.print("Procurando botão de salvar (imagem)...", style="bold cyan")
121
- caminho = r'assets\\extracao_relatorios\\btn_salvar.png'
122
- if os.path.isfile(caminho):
123
- pos = pyautogui.locateCenterOnScreen(caminho, confidence=0.9)
122
+ caminho_img = r'assets\\extracao_relatorios\\btn_salvar.png'
123
+ if os.path.isfile(caminho_img):
124
+ pos = pyautogui.locateCenterOnScreen(caminho_img, confidence=0.9)
124
125
  if pos:
125
126
  pyautogui.click(pos)
126
127
  console.print("Clique realizado no botão salvar", style="bold green")
@@ -131,49 +132,139 @@ async def extracao_saldo_estoque(task: RpaProcessoEntradaDTO):
131
132
 
132
133
  await worker_sleep(8)
133
134
 
135
+ # 2) Selecionar formato "Excel" na janela TFrmRelatorioFormato
134
136
  console.print("Selecionando formato Excel...", style="bold cyan")
135
- app = Application().connect(class_name="TFrmRelatorioFormato")
136
- main_window = app["TFrmRelatorioFormato"]
137
- combo = main_window.ComboBox
138
- console.print(f"Itens do ComboBox: {combo.texts()}", style="bold yellow")
139
- combo.select(8)
140
-
141
- await worker_sleep(5)
142
-
143
- console.print("Confirmando salvar...", style="bold cyan")
144
- main_window.child_window(class_name="TBitBtn", found_index=1).click_input()
137
+ try:
138
+ app_fmt = Application().connect(class_name="TFrmRelatorioFormato", timeout=10)
139
+ win_fmt = app_fmt["TFrmRelatorioFormato"]
140
+ win_fmt.wait("visible", timeout=10)
141
+
142
+ combo = win_fmt.ComboBox
143
+ textos = combo.texts()
144
+ console.print(f"Itens do ComboBox: {textos}", style="bold yellow")
145
+
146
+ # Se souber o índice correto, mantenha. Caso contrário, tente por texto contendo 'Excel'
147
+ try:
148
+ combo.select(8)
149
+ except Exception:
150
+ alvo = None
151
+ for i, t in enumerate(textos):
152
+ if "EXCEL" in str(t).upper() or "XLSX" in str(t).upper():
153
+ alvo = i
154
+ break
155
+ if alvo is not None:
156
+ combo.select(alvo)
157
+ else:
158
+ console.print("Não foi possível localizar a opção de Excel no ComboBox.", style="bold red")
159
+ tentativa += 1
160
+ await worker_sleep(2)
161
+ continue
162
+
163
+ await worker_sleep(1)
164
+
165
+ # Botão OK/Confirmar na janela de formato
166
+ # Em muitos Delphi VCL, TBitBtn com found_index=1 costuma ser OK.
167
+ win_fmt.child_window(class_name="TBitBtn", found_index=1).wait("enabled", timeout=5)
168
+ win_fmt.child_window(class_name="TBitBtn", found_index=1).click_input()
169
+ except Exception as e:
170
+ console.print(f"Falha ao selecionar formato: {e}", style="bold red")
171
+ tentativa += 1
172
+ await worker_sleep(3)
173
+ continue
145
174
 
146
175
  await worker_sleep(5)
147
176
 
177
+ # 3) Janela "Salvar para arquivo"
148
178
  console.print("Abrindo janela de salvar arquivo...", style="bold cyan")
149
- app = Application().connect(title_re="Salvar para arquivo", timeout=30)
150
- main_window = app.window(title_re="Salvar para arquivo")
179
+ try:
180
+ app_save = Application().connect(title_re="Salvar para arquivo", timeout=30)
181
+ win_save = app_save.window(title_re="Salvar para arquivo")
182
+ win_save.wait("visible", timeout=30)
183
+ except Exception as e:
184
+ console.print(f"Não achou a janela 'Salvar para arquivo': {e}", style="bold red")
185
+ tentativa += 1
186
+ await worker_sleep(3)
187
+ continue
151
188
 
189
+ # Caminho do arquivo a salvar
152
190
  caminho_arquivo = rf"C:\Users\automatehub\Downloads\saldo_estoque_{periodo_format}_{filial}.xlsx"
153
- campo_nome = main_window.child_window(class_name="Edit", control_id=1148).wrapper_object()
154
- campo_nome.set_edit_text(caminho_arquivo)
155
- console.print(f"Arquivo configurado para: {caminho_arquivo}", style="bold green")
191
+
192
+ # Se já existe, removemos para evitar pop-up de confirmação
193
+ if os.path.exists(caminho_arquivo):
194
+ try:
195
+ os.remove(caminho_arquivo)
196
+ console.print("Arquivo existente removido para evitar prompt de sobrescrita.", style="bold yellow")
197
+ except Exception as e:
198
+ console.print(f"Não foi possível remover o arquivo existente: {e}", style="bold red")
199
+
200
+ try:
201
+ # Campo "Nome" (Edit, control_id=1148)
202
+ campo_nome = win_save.child_window(class_name="Edit", control_id=1148).wrapper_object()
203
+ campo_nome.set_focus()
204
+ # limpa conteúdo
205
+ try:
206
+ campo_nome.set_edit_text("")
207
+ except Exception:
208
+ # fallback limpando com Ctrl+A + Delete
209
+ campo_nome.type_keys("^a{DELETE}", pause=0.02)
210
+
211
+ # digita caminho
212
+ campo_nome.type_keys(caminho_arquivo, with_spaces=True, pause=0.01)
213
+ console.print(f"Arquivo configurado para: {caminho_arquivo}", style="bold green")
214
+
215
+ await worker_sleep(1)
216
+
217
+ # Botão Salvar (primeiro Button)
218
+ btn_salvar = win_save.child_window(class_name="Button", found_index=0)
219
+ btn_salvar.wait("enabled", timeout=10)
220
+ btn_salvar.click_input()
221
+ except Exception as e:
222
+ console.print(f"Erro ao confirmar salvar: {e}", style="bold red")
223
+ tentativa += 1
224
+ await worker_sleep(3)
225
+ continue
156
226
 
157
227
  await worker_sleep(2)
158
-
159
- main_window.child_window(class_name="Button", found_index=0).click_input()
160
228
 
161
- await worker_sleep(4)
229
+ # 3.1) Tratar confirmação de sobrescrita, se aparecer
230
+ try:
231
+ # Pode vir em PT/EN dependendo do SO
232
+ # Título comum: "Confirm Save As" (EN) ou "Confirmar Salvar Como" (PT)
233
+ try:
234
+ app_conf = Application().connect(title_re="Confirm(ar)?( )?Salvar( )?Como|Confirm Save As", timeout=3)
235
+ win_conf = app_conf.window(title_re="Confirm(ar)?( )?Salvar( )?Como|Confirm Save As")
236
+ win_conf.wait("visible", timeout=3)
237
+ # Botões costumam ser "Sim"/"Yes" como class_name="Button"
238
+ # Tente o primeiro botão (Yes/Sim)
239
+ win_conf.child_window(class_name="Button", found_index=0).click_input()
240
+ console.print("Confirmação de sobrescrita respondida.", style="bold yellow")
241
+ except Exception:
242
+ pass
243
+ except Exception:
244
+ pass
245
+
246
+ await worker_sleep(2)
162
247
 
248
+ # 4) Aguardar o processamento/Printing encerrar
163
249
  console.print("Aguardando finalização do processo de impressão/salvamento...", style="bold cyan")
164
250
  try:
165
- app = Application().connect(title_re="Printing")
166
- janela = app.window(title_re="Printing")
167
- janela.wait_not("visible", timeout=60)
168
- console.print("Janela 'Printing' fechada.", style="bold green")
251
+ app_print = Application().connect(title_re="Printing", timeout=5)
252
+ win_print = app_print.window(title_re="Printing")
253
+ try:
254
+ win_print.wait_not("visible", timeout=60)
255
+ console.print("Janela 'Printing' fechada.", style="bold green")
256
+ except Exception:
257
+ console.print("Janela 'Printing' não fechou no tempo esperado. Seguindo.", style="bold yellow")
169
258
  except findwindows.ElementNotFoundError:
170
259
  console.print("Janela 'Printing' não apareceu.", style="bold yellow")
260
+ except Exception as e:
261
+ console.print(f"Erro ao aguardar 'Printing': {e}", style="bold yellow")
171
262
 
172
- # Verifica se o arquivo foi salvo
263
+ # 5) Validar arquivo salvo
173
264
  if os.path.exists(caminho_arquivo):
174
265
  console.print(f"Arquivo encontrado: {caminho_arquivo}", style="bold green")
175
- with open(caminho_arquivo, "rb") as file:
176
- file_bytes = io.BytesIO(file.read())
266
+ with open(caminho_arquivo, "rb") as f:
267
+ file_bytes = io.BytesIO(f.read())
177
268
  sucesso = True
178
269
  else:
179
270
  console.print("Arquivo não encontrado, tentando novamente...", style="bold red")
@@ -282,105 +282,169 @@ async def extracao_saldo_estoque_fiscal(
282
282
 
283
283
  await worker_sleep(2)
284
284
 
285
- # Clicar em salvar
286
- caminho = r"assets\\extracao_relatorios\\btn_salvar.png"
287
- # Verifica se o arquivo existe
288
- if os.path.isfile(caminho):
289
- print("A imagem existe:", caminho)
290
-
291
- # Procura a imagem na tela
292
- pos = pyautogui.locateCenterOnScreen(
293
- caminho, confidence=0.9
294
- ) # ajuste o confidence se necessário
295
- if pos:
296
- pyautogui.click(pos) # clica no centro da imagem
297
- print("Clique realizado na imagem.")
285
+ max_tentativas = 5
286
+ tentativa = 1
287
+ sucesso = False
288
+
289
+ while tentativa <= max_tentativas and not sucesso:
290
+ console.print(f"Tentativa {tentativa} de {max_tentativas}", style="bold cyan")
291
+
292
+ # 1) Abrir o picker de formatos pelo botão (imagem)
293
+ console.print("Procurando botão de salvar (imagem)...", style="bold cyan")
294
+ caminho_img = r'assets\\extracao_relatorios\\btn_salvar.png'
295
+ if os.path.isfile(caminho_img):
296
+ pos = pyautogui.locateCenterOnScreen(caminho_img, confidence=0.9)
297
+ if pos:
298
+ pyautogui.click(pos)
299
+ console.print("Clique realizado no botão salvar", style="bold green")
300
+ else:
301
+ console.print("Imagem encontrada mas não está visível na tela", style="bold yellow")
298
302
  else:
299
- print("Imagem encontrada no disco, mas não está visível na tela.")
300
- else:
301
- print("A imagem NÃO existe:", caminho)
302
-
303
- await worker_sleep(2)
304
-
305
- # Conecta na janela Configuração para Salvar Arquivo
306
- app = Application().connect(class_name="TFrmRelatorioFormato", found_index=0)
307
- main_window = app["TFrmRelatorioFormato"]
308
- main_window.set_focus()
309
- # Acessa o ComboBox pelo identificador conhecido
310
- combo = main_window.ComboBox
303
+ console.print("Imagem do botão salvar NÃO existe", style="bold red")
311
304
 
312
- # Garante que existe "Excel" na lista
313
- itens = combo.texts()
314
- print("Itens do ComboBox:", itens)
315
-
316
- # Seleciona o Excel correto (o segundo da lista, índice 8)
317
- combo.select(8)
318
-
319
- await worker_sleep(2)
320
-
321
- # Clicar em Salvar
322
- btn_salvar = main_window.child_window(
323
- class_name="TBitBtn", found_index=1
324
- ).click_input()
305
+ await worker_sleep(8)
325
306
 
326
- await worker_sleep(5)
327
-
328
- # Conecta na janela "Salvar para arquivo"
329
- app = Application().connect(title_re="Salvar para arquivo", timeout=30)
330
- main_window = app.window(title_re="Salvar para arquivo")
331
-
332
- # Campo Nome (Edit) - use set_edit_text para evitar problemas de escape
333
- campo_nome = main_window.child_window(
334
- class_name="Edit", control_id=1148
335
- ).wrapper_object()
336
- caminho_arquivo = rf"C:\Users\automatehub\Downloads\saldo_estoque_fiscal_{periodo_format}_{filial}.xlsx"
337
- campo_nome.set_focus()
338
- campo_nome.set_edit_text(caminho_arquivo)
339
-
340
- print("✅ Texto inserido no campo Nome")
341
-
342
- await worker_sleep(3)
343
-
344
- # Clicar em Salvar
345
- main_window.child_window(class_name="TBitBtn", found_index=1).click_input()
346
-
347
- await worker_sleep(5)
348
-
349
- # Conecta na janela "Salvar para arquivo"
350
- app = Application().connect(title_re="Salvar para arquivo", timeout=30)
351
- main_window = app.window(title_re="Salvar para arquivo")
352
-
353
- # Campo Nome (Edit) - use set_edit_text para evitar problemas de escape
354
- campo_nome = main_window.child_window(
355
- class_name="Edit", control_id=1148
356
- ).wrapper_object()
357
- caminho_arquivo = f"C:\\Users\\automatehub\\Downloads\\saldo_estoque_fiscal_{periodo_format}_{filial}.xlsx"
358
- campo_nome.set_focus()
359
- campo_nome.set_edit_text(caminho_arquivo)
307
+ # 2) Selecionar formato "Excel" na janela TFrmRelatorioFormato
308
+ console.print("Selecionando formato Excel...", style="bold cyan")
309
+ try:
310
+ app_fmt = Application().connect(class_name="TFrmRelatorioFormato", timeout=10)
311
+ win_fmt = app_fmt["TFrmRelatorioFormato"]
312
+ win_fmt.wait("visible", timeout=10)
313
+
314
+ combo = win_fmt.ComboBox
315
+ textos = combo.texts()
316
+ console.print(f"Itens do ComboBox: {textos}", style="bold yellow")
317
+
318
+ # Se souber o índice correto, mantenha. Caso contrário, tente por texto contendo 'Excel'
319
+ try:
320
+ combo.select(8)
321
+ except Exception:
322
+ alvo = None
323
+ for i, t in enumerate(textos):
324
+ if "EXCEL" in str(t).upper() or "XLSX" in str(t).upper():
325
+ alvo = i
326
+ break
327
+ if alvo is not None:
328
+ combo.select(alvo)
329
+ else:
330
+ console.print("Não foi possível localizar a opção de Excel no ComboBox.", style="bold red")
331
+ tentativa += 1
332
+ await worker_sleep(2)
333
+ continue
334
+
335
+ await worker_sleep(1)
336
+
337
+ # Botão OK/Confirmar na janela de formato
338
+ win_fmt.child_window(class_name="TBitBtn", found_index=1).wait("enabled", timeout=5)
339
+ win_fmt.child_window(class_name="TBitBtn", found_index=1).click_input()
340
+ except Exception as e:
341
+ console.print(f"Falha ao selecionar formato: {e}", style="bold red")
342
+ tentativa += 1
343
+ await worker_sleep(3)
344
+ continue
360
345
 
361
- print("✅ Texto inserido no campo Nome")
346
+ await worker_sleep(5)
362
347
 
363
- await worker_sleep(2)
348
+ # 3) Janela "Salvar para arquivo"
349
+ console.print("Abrindo janela de salvar arquivo...", style="bold cyan")
350
+ try:
351
+ app_save = Application().connect(title_re="Salvar para arquivo", timeout=30)
352
+ win_save = app_save.window(title_re="Salvar para arquivo")
353
+ win_save.wait("visible", timeout=30)
354
+ except Exception as e:
355
+ console.print(f"Não achou a janela 'Salvar para arquivo': {e}", style="bold red")
356
+ tentativa += 1
357
+ await worker_sleep(3)
358
+ continue
359
+
360
+ # Caminho do arquivo a salvar
361
+ caminho_arquivo = rf"C:\Users\automatehub\Downloads\saldo_estoque_fiscal_{periodo_format}_{filial}.xlsx"
362
+
363
+ # Se já existe, removemos para evitar pop-up de confirmação
364
+ if os.path.exists(caminho_arquivo):
365
+ try:
366
+ os.remove(caminho_arquivo)
367
+ console.print("Arquivo existente removido para evitar prompt de sobrescrita.", style="bold yellow")
368
+ except Exception as e:
369
+ console.print(f"Não foi possível remover o arquivo existente: {e}", style="bold red")
364
370
 
365
- # Clicar em ok para salvar
366
- main_window.child_window(class_name="Button", found_index=0).click_input()
371
+ try:
372
+ # Campo "Nome" (Edit, control_id=1148)
373
+ campo_nome = win_save.child_window(class_name="Edit", control_id=1148).wrapper_object()
374
+ campo_nome.set_focus()
375
+ # limpa conteúdo
376
+ try:
377
+ campo_nome.set_edit_text("")
378
+ except Exception:
379
+ # fallback limpando com Ctrl+A + Delete
380
+ campo_nome.type_keys("^a{DELETE}", pause=0.02)
381
+
382
+ # digita caminho
383
+ campo_nome.type_keys(caminho_arquivo, with_spaces=True, pause=0.01)
384
+ console.print(f"Arquivo configurado para: {caminho_arquivo}", style="bold green")
385
+
386
+ await worker_sleep(1)
387
+
388
+ # Botão Salvar (primeiro Button)
389
+ btn_salvar = win_save.child_window(class_name="Button", found_index=0)
390
+ btn_salvar.wait("enabled", timeout=10)
391
+ btn_salvar.click_input()
392
+ except Exception as e:
393
+ console.print(f"Erro ao confirmar salvar: {e}", style="bold red")
394
+ tentativa += 1
395
+ await worker_sleep(3)
396
+ continue
367
397
 
368
- await worker_sleep(20)
398
+ await worker_sleep(2)
369
399
 
370
- # caminho_img = r"assets\\extracao_relatorios\\janela_printing.png"
400
+ # 3.1) Tratar confirmação de sobrescrita, se aparecer
401
+ try:
402
+ # Pode vir em PT/EN dependendo do SO
403
+ # Título comum: "Confirm Save As" (EN) ou "Confirmar Salvar Como" (PT)
404
+ try:
405
+ app_conf = Application().connect(title_re="Confirm(ar)?( )?Salvar( )?Como|Confirm Save As", timeout=3)
406
+ win_conf = app_conf.window(title_re="Confirm(ar)?( )?Salvar( )?Como|Confirm Save As")
407
+ win_conf.wait("visible", timeout=3)
408
+ # Botões costumam ser "Sim"/"Yes" como class_name="Button"
409
+ # Tente o primeiro botão (Yes/Sim)
410
+ win_conf.child_window(class_name="Button", found_index=0).click_input()
411
+ console.print("Confirmação de sobrescrita respondida.", style="bold yellow")
412
+ except Exception:
413
+ pass
414
+ except Exception:
415
+ pass
371
416
 
372
- # Aguarda até a janela com título "Printing" (ou "Salvando...") fechar
417
+ await worker_sleep(2)
373
418
 
374
- try:
375
- app = Application().connect(title_re="Printing") # conecta se existir
376
- janela = app.window(title_re="Printing")
419
+ # 4) Aguardar o processamento/Printing encerrar
420
+ console.print("Aguardando finalização do processo de impressão/salvamento...", style="bold cyan")
421
+ try:
422
+ app_print = Application().connect(title_re="Printing", timeout=5)
423
+ win_print = app_print.window(title_re="Printing")
424
+ try:
425
+ win_print.wait_not("visible", timeout=60)
426
+ console.print("Janela 'Printing' fechada.", style="bold green")
427
+ except Exception:
428
+ console.print("Janela 'Printing' não fechou no tempo esperado. Seguindo.", style="bold yellow")
429
+ except findwindows.ElementNotFoundError:
430
+ console.print("Janela 'Printing' não apareceu.", style="bold yellow")
431
+ except Exception as e:
432
+ console.print(f"Erro ao aguardar 'Printing': {e}", style="bold yellow")
433
+
434
+ # 5) Validar arquivo salvo
435
+ if os.path.exists(caminho_arquivo):
436
+ console.print(f"Arquivo encontrado: {caminho_arquivo}", style="bold green")
437
+ with open(caminho_arquivo, "rb") as f:
438
+ file_bytes = io.BytesIO(f.read())
439
+ sucesso = True
440
+ else:
441
+ console.print("Arquivo não encontrado, tentando novamente...", style="bold red")
442
+ tentativa += 1
443
+ await worker_sleep(3)
377
444
 
378
- print("⏳ Aguardando a janela 'Printing' sumir...")
379
- janela.wait_not("visible", timeout=60) # espera até 60 segundos
380
- print("✅ Janela 'Printing' fechada.")
445
+ if not sucesso:
446
+ console.print("Falha após 5 tentativas. Arquivo não foi gerado.", style="bold red")
381
447
 
382
- except findwindows.ElementNotFoundError:
383
- print("⚠️ Janela 'Printing' não estava aberta.")
384
448
 
385
449
  nome_com_extensao = f"saldo_estoque_fiscal_{periodo_format}_{filial}.xlsx"
386
450
  # lê o arquivo
@@ -424,3 +488,4 @@ async def extracao_saldo_estoque_fiscal(
424
488
  status=RpaHistoricoStatusEnum.Falha,
425
489
  tags=[RpaTagDTO(descricao=RpaTagEnum.Tecnico)],
426
490
  )
491
+