worker-automate-hub 0.5.761__tar.gz → 0.5.763__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.
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/PKG-INFO +1 -1
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/pyproject.toml +1 -1
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/tasks/jobs/extracao_saldo_estoque.py +119 -28
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/tasks/jobs/extracao_saldo_estoque_fiscal.py +105 -51
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/README.md +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/__init__.py +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/api/__init__.py +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/api/ahead_service.py +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/api/client.py +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/api/datalake_service.py +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/api/helpers/__init__.py +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/api/helpers/api_helpers.py +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/api/rdp_service.py +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/api/rpa_fila_service.py +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/api/rpa_historico_service.py +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/api/webhook_service.py +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/cli.py +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/config/__init__.py +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/config/settings.py +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/config.py +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/core/so_manipulation.py +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/decorators/__init__.py +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/decorators/deprecation.py +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/decorators/rate_limit.py +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/decorators/repeat.py +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/decorators/retry.py +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/decorators/singleton.py +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/decorators/timeit.py +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/models/__init__.py +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/models/dao/__init__.py +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/models/dao/rpa_configuracao.py +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/models/dao/rpa_fila.py +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/models/dao/rpa_historico.py +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/models/dao/rpa_processo.py +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/models/dao/rpa_robo.py +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/models/dto/__init__.py +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/models/dto/rpa_historico_request_dto.py +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/models/dto/rpa_processo_entrada_dto.py +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/models/dto/rpa_processo_rdp_dto.py +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/models/dto/rpa_sap_dto.py +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/models/dto/rpa_sistema_dto.py +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/tasks/__init__.py +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/tasks/jobs/__init__.py +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/tasks/jobs/abertura_livros_fiscais.py +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/tasks/jobs/coleta_dje_process.py +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/tasks/jobs/conexao_rdp.py +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/tasks/jobs/cte_manual.py +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/tasks/jobs/cte_xml.py +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/tasks/jobs/descartes.py +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/tasks/jobs/devolucao_ctf.py +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/tasks/jobs/devolucao_ctf_35.py +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/tasks/jobs/devolucao_prazo_a_faturar.py +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/tasks/jobs/ecac_estadual_go.py +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/tasks/jobs/ecac_estadual_main.py +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/tasks/jobs/ecac_estadual_mt.py +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/tasks/jobs/ecac_estadual_sc.py +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/tasks/jobs/ecac_estadual_sp.py +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/tasks/jobs/ecac_federal.py +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/tasks/jobs/entrada_cte_1353.py +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/tasks/jobs/entrada_cte_333.py +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/tasks/jobs/entrada_de_notas_15.py +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/tasks/jobs/entrada_de_notas_16.py +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/tasks/jobs/entrada_de_notas_207.py +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/tasks/jobs/entrada_de_notas_32.py +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/tasks/jobs/entrada_de_notas_33.py +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/tasks/jobs/entrada_de_notas_34.py +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/tasks/jobs/entrada_de_notas_36.py +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/tasks/jobs/entrada_de_notas_39.py +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/tasks/jobs/entrada_de_notas_500.py +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/tasks/jobs/entrada_de_notas_503.py +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/tasks/jobs/entrada_de_notas_505.py +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/tasks/jobs/entrada_de_notas_7139.py +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/tasks/jobs/entrada_de_notas_9.py +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/tasks/jobs/entrada_de_notas_9000.py +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/tasks/jobs/exemplo_processo.py +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/tasks/jobs/extracao_fechamento_contabil.py +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/tasks/jobs/extracao_fechamento_emsys.py +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/tasks/jobs/fechar_conexao_rdp.py +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/tasks/jobs/fidc_exportacao_docs_portal_b2b.py +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/tasks/jobs/fidc_gerar_nosso_numero.py +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/tasks/jobs/fidc_remessa_cobranca_cnab240.py +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/tasks/jobs/fidc_retorno_cobranca.py +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/tasks/jobs/geracao_aprovacao_pedidos.py +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/tasks/jobs/geracao_aprovacao_pedidos_novo.py +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/tasks/jobs/integracao_contabil.py +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/tasks/jobs/integracao_contabil_generica.py +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/tasks/jobs/lancamento_pis_cofins.py +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/tasks/jobs/lancamento_rateio.py +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/tasks/jobs/login_emsys.py +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/tasks/jobs/login_emsys_versao_especifica.py +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/tasks/jobs/notas_faturamento_sap.py +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/tasks/jobs/opex_capex.py +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/tasks/jobs/playground.py +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/tasks/jobs/sped_fiscal.py +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/tasks/jobs/transferencias.py +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/tasks/task_definitions.py +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/tasks/task_executor.py +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/utils/__init__.py +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/utils/env.py +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/utils/get_creds_gworkspace.py +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/utils/logger.py +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/utils/toast.py +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/utils/updater.py +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/utils/util.py +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/utils/utils_nfe_entrada.py +0 -0
- {worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/worker.py +0 -0
@@ -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
|
-
|
122
|
-
if os.path.isfile(
|
123
|
-
pos = pyautogui.locateCenterOnScreen(
|
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
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
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
|
-
|
150
|
-
|
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
|
-
|
154
|
-
|
155
|
-
|
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
|
-
|
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
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
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
|
-
#
|
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
|
176
|
-
file_bytes = io.BytesIO(
|
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")
|
@@ -1,10 +1,10 @@
|
|
1
1
|
import asyncio
|
2
2
|
import os
|
3
3
|
from datetime import datetime
|
4
|
-
from pywinauto import Application, timings, findwindows, keyboard
|
4
|
+
from pywinauto import Application, timings, findwindows, keyboard, Desktop
|
5
5
|
import sys
|
6
6
|
import io
|
7
|
-
|
7
|
+
import win32gui
|
8
8
|
# sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', '..')))
|
9
9
|
|
10
10
|
from worker_automate_hub.models.dto.rpa_historico_request_dto import (
|
@@ -282,14 +282,18 @@ async def extracao_saldo_estoque_fiscal(
|
|
282
282
|
|
283
283
|
await worker_sleep(2)
|
284
284
|
|
285
|
+
|
285
286
|
max_tentativas = 5
|
286
287
|
tentativa = 1
|
287
288
|
sucesso = False
|
288
289
|
|
290
|
+
# defina caminho_arquivo ANTES para não ficar indefinido
|
291
|
+
caminho_arquivo = rf"C:\Users\automatehub\Downloads\saldo_estoque_fiscal_{periodo_format}_{filial}.xlsx"
|
292
|
+
|
289
293
|
while tentativa <= max_tentativas and not sucesso:
|
290
294
|
console.print(f"Tentativa {tentativa} de {max_tentativas}", style="bold cyan")
|
291
295
|
|
292
|
-
# 1) Abrir o picker
|
296
|
+
# 1) Abrir o picker pelo botão (imagem)
|
293
297
|
console.print("Procurando botão de salvar (imagem)...", style="bold cyan")
|
294
298
|
caminho_img = r'assets\\extracao_relatorios\\btn_salvar.png'
|
295
299
|
if os.path.isfile(caminho_img):
|
@@ -304,39 +308,92 @@ async def extracao_saldo_estoque_fiscal(
|
|
304
308
|
|
305
309
|
await worker_sleep(8)
|
306
310
|
|
307
|
-
# 2) Selecionar formato
|
311
|
+
# 2) Selecionar formato Excel (desambiguando múltiplas TFrmRelatorioFormato)
|
308
312
|
console.print("Selecionando formato Excel...", style="bold cyan")
|
309
313
|
try:
|
310
|
-
|
311
|
-
|
312
|
-
|
314
|
+
desktop = Desktop(backend="win32")
|
315
|
+
|
316
|
+
# Liste todas as visíveis
|
317
|
+
wins_visiveis = desktop.windows(class_name="TFrmRelatorioFormato", visible_only=True)
|
318
|
+
if not wins_visiveis:
|
319
|
+
raise RuntimeError("Janela de formato não apareceu.")
|
320
|
+
|
321
|
+
# 2.1) Tente a janela em foco (foreground)
|
322
|
+
h_fore = win32gui.GetForegroundWindow()
|
323
|
+
alvo = None
|
324
|
+
for w in wins_visiveis:
|
325
|
+
if w.handle == h_fore:
|
326
|
+
alvo = w
|
327
|
+
break
|
328
|
+
|
329
|
+
# 2.2) Se não estiver em foco, pegue a que contém um TComboBox (a 'Configuração para Salvar arq...')
|
330
|
+
if alvo is None:
|
331
|
+
candidatos = []
|
332
|
+
for w in wins_visiveis:
|
333
|
+
try:
|
334
|
+
if w.child_window(class_name="TComboBox").exists(timeout=0.8):
|
335
|
+
candidatos.append(w)
|
336
|
+
except Exception:
|
337
|
+
pass
|
338
|
+
if candidatos:
|
339
|
+
alvo = candidatos[-1] # a mais recente
|
340
|
+
else:
|
341
|
+
alvo = wins_visiveis[-1] # fallback
|
342
|
+
|
343
|
+
# Trabalhe via WindowSpecification
|
344
|
+
spec_fmt = desktop.window(handle=alvo.handle)
|
345
|
+
spec_fmt.wait("visible", timeout=10)
|
346
|
+
win_fmt = spec_fmt.wrapper_object()
|
347
|
+
win_fmt.set_focus()
|
348
|
+
|
349
|
+
# Acessar o ComboBox
|
350
|
+
try:
|
351
|
+
combo_spec = spec_fmt.child_window(class_name="TComboBox")
|
352
|
+
except Exception:
|
353
|
+
combo_spec = spec_fmt.child_window(control_type="ComboBox")
|
354
|
+
combo_spec.wait("exists enabled", timeout=10)
|
355
|
+
combo = combo_spec.wrapper_object()
|
313
356
|
|
314
|
-
combo = win_fmt.ComboBox
|
315
357
|
textos = combo.texts()
|
316
358
|
console.print(f"Itens do ComboBox: {textos}", style="bold yellow")
|
317
359
|
|
318
|
-
#
|
360
|
+
# Seleção por índice conhecido; fallback por texto
|
319
361
|
try:
|
320
362
|
combo.select(8)
|
321
363
|
except Exception:
|
322
|
-
|
364
|
+
alvo_idx = None
|
323
365
|
for i, t in enumerate(textos):
|
324
366
|
if "EXCEL" in str(t).upper() or "XLSX" in str(t).upper():
|
325
|
-
|
367
|
+
alvo_idx = i
|
326
368
|
break
|
327
|
-
if
|
328
|
-
combo.select(alvo)
|
329
|
-
else:
|
369
|
+
if alvo_idx is None:
|
330
370
|
console.print("Não foi possível localizar a opção de Excel no ComboBox.", style="bold red")
|
331
371
|
tentativa += 1
|
332
372
|
await worker_sleep(2)
|
333
373
|
continue
|
374
|
+
combo.select(alvo_idx)
|
334
375
|
|
335
376
|
await worker_sleep(1)
|
336
377
|
|
337
|
-
#
|
338
|
-
|
339
|
-
|
378
|
+
# Clique em OK
|
379
|
+
btn_ok_spec = spec_fmt.child_window(class_name="TBitBtn", found_index=1)
|
380
|
+
btn_ok_spec.wait("enabled", timeout=5)
|
381
|
+
btn_ok_spec.click_input()
|
382
|
+
|
383
|
+
# Aguarde a janela de formato desaparecer
|
384
|
+
try:
|
385
|
+
spec_fmt.wait_not("visible", timeout=10)
|
386
|
+
except Exception:
|
387
|
+
pass
|
388
|
+
|
389
|
+
# Feche possíveis duplicatas remanescentes (defensivo)
|
390
|
+
for w in desktop.windows(class_name="TFrmRelatorioFormato", visible_only=True):
|
391
|
+
if w.handle != alvo.handle:
|
392
|
+
try:
|
393
|
+
w.close()
|
394
|
+
except Exception:
|
395
|
+
pass
|
396
|
+
|
340
397
|
except Exception as e:
|
341
398
|
console.print(f"Falha ao selecionar formato: {e}", style="bold red")
|
342
399
|
tentativa += 1
|
@@ -348,19 +405,17 @@ async def extracao_saldo_estoque_fiscal(
|
|
348
405
|
# 3) Janela "Salvar para arquivo"
|
349
406
|
console.print("Abrindo janela de salvar arquivo...", style="bold cyan")
|
350
407
|
try:
|
351
|
-
app_save = Application().connect(title_re="Salvar para arquivo", timeout=30)
|
352
|
-
|
353
|
-
|
408
|
+
app_save = Application(backend="win32").connect(title_re="Salvar para arquivo|Salvar como|Save As", timeout=30)
|
409
|
+
spec_save = app_save.window(title_re="Salvar para arquivo|Salvar como|Save As")
|
410
|
+
spec_save.wait("visible", timeout=30)
|
411
|
+
win_save = spec_save.wrapper_object()
|
354
412
|
except Exception as e:
|
355
413
|
console.print(f"Não achou a janela 'Salvar para arquivo': {e}", style="bold red")
|
356
414
|
tentativa += 1
|
357
415
|
await worker_sleep(3)
|
358
416
|
continue
|
359
417
|
|
360
|
-
#
|
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
|
418
|
+
# 3.1) Remover arquivo pré-existente
|
364
419
|
if os.path.exists(caminho_arquivo):
|
365
420
|
try:
|
366
421
|
os.remove(caminho_arquivo)
|
@@ -368,27 +423,32 @@ async def extracao_saldo_estoque_fiscal(
|
|
368
423
|
except Exception as e:
|
369
424
|
console.print(f"Não foi possível remover o arquivo existente: {e}", style="bold red")
|
370
425
|
|
426
|
+
# 3.2) Preencher nome e salvar
|
371
427
|
try:
|
372
|
-
|
373
|
-
|
428
|
+
campo_spec = spec_save.child_window(class_name="Edit", control_id=1148)
|
429
|
+
campo_spec.wait("exists enabled visible", timeout=10)
|
430
|
+
campo_nome = campo_spec.wrapper_object()
|
374
431
|
campo_nome.set_focus()
|
375
|
-
# limpa conteúdo
|
376
432
|
try:
|
377
433
|
campo_nome.set_edit_text("")
|
378
434
|
except Exception:
|
379
|
-
# fallback limpando com Ctrl+A + Delete
|
380
435
|
campo_nome.type_keys("^a{DELETE}", pause=0.02)
|
381
436
|
|
382
|
-
# digita caminho
|
383
437
|
campo_nome.type_keys(caminho_arquivo, with_spaces=True, pause=0.01)
|
384
438
|
console.print(f"Arquivo configurado para: {caminho_arquivo}", style="bold green")
|
385
439
|
|
386
440
|
await worker_sleep(1)
|
387
441
|
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
442
|
+
btn_salvar_spec = spec_save.child_window(class_name="Button", found_index=0)
|
443
|
+
btn_salvar_spec.wait("enabled", timeout=10)
|
444
|
+
btn_salvar_spec.click_input()
|
445
|
+
|
446
|
+
# Esperar a janela sumir
|
447
|
+
try:
|
448
|
+
spec_save.wait_not("visible", timeout=15)
|
449
|
+
except Exception:
|
450
|
+
pass
|
451
|
+
|
392
452
|
except Exception as e:
|
393
453
|
console.print(f"Erro ao confirmar salvar: {e}", style="bold red")
|
394
454
|
tentativa += 1
|
@@ -397,32 +457,27 @@ async def extracao_saldo_estoque_fiscal(
|
|
397
457
|
|
398
458
|
await worker_sleep(2)
|
399
459
|
|
400
|
-
# 3.
|
460
|
+
# 3.3) Confirmar sobrescrita (se houver)
|
401
461
|
try:
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
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
|
462
|
+
app_conf = Application(backend="win32").connect(
|
463
|
+
title_re="Confirm(ar)?( )?Salvar( )?Como|Confirm Save As", timeout=3
|
464
|
+
)
|
465
|
+
spec_conf = app_conf.window(title_re="Confirm(ar)?( )?Salvar( )?Como|Confirm Save As")
|
466
|
+
spec_conf.wait("visible", timeout=3)
|
467
|
+
spec_conf.child_window(class_name="Button", found_index=0).click_input()
|
468
|
+
console.print("Confirmação de sobrescrita respondida.", style="bold yellow")
|
414
469
|
except Exception:
|
415
470
|
pass
|
416
471
|
|
417
472
|
await worker_sleep(2)
|
418
473
|
|
419
|
-
# 4) Aguardar
|
474
|
+
# 4) Aguardar 'Printing' (se existir)
|
420
475
|
console.print("Aguardando finalização do processo de impressão/salvamento...", style="bold cyan")
|
421
476
|
try:
|
422
|
-
app_print = Application().connect(title_re="Printing", timeout=5)
|
423
|
-
|
477
|
+
app_print = Application(backend="win32").connect(title_re="Printing", timeout=5)
|
478
|
+
spec_print = app_print.window(title_re="Printing")
|
424
479
|
try:
|
425
|
-
|
480
|
+
spec_print.wait_not("visible", timeout=60)
|
426
481
|
console.print("Janela 'Printing' fechada.", style="bold green")
|
427
482
|
except Exception:
|
428
483
|
console.print("Janela 'Printing' não fechou no tempo esperado. Seguindo.", style="bold yellow")
|
@@ -445,7 +500,6 @@ async def extracao_saldo_estoque_fiscal(
|
|
445
500
|
if not sucesso:
|
446
501
|
console.print("Falha após 5 tentativas. Arquivo não foi gerado.", style="bold red")
|
447
502
|
|
448
|
-
|
449
503
|
nome_com_extensao = f"saldo_estoque_fiscal_{periodo_format}_{filial}.xlsx"
|
450
504
|
# lê o arquivo
|
451
505
|
print(caminho_arquivo)
|
File without changes
|
File without changes
|
{worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/api/__init__.py
RENAMED
File without changes
|
{worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/api/ahead_service.py
RENAMED
File without changes
|
{worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/api/client.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/api/rdp_service.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/config/__init__.py
RENAMED
File without changes
|
{worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/config/settings.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/decorators/repeat.py
RENAMED
File without changes
|
{worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/decorators/retry.py
RENAMED
File without changes
|
File without changes
|
{worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/decorators/timeit.py
RENAMED
File without changes
|
{worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/models/__init__.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/tasks/__init__.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/utils/__init__.py
RENAMED
File without changes
|
{worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/utils/env.py
RENAMED
File without changes
|
File without changes
|
{worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/utils/logger.py
RENAMED
File without changes
|
{worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/utils/toast.py
RENAMED
File without changes
|
{worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/utils/updater.py
RENAMED
File without changes
|
{worker_automate_hub-0.5.761 → worker_automate_hub-0.5.763}/worker_automate_hub/utils/util.py
RENAMED
File without changes
|
File without changes
|
File without changes
|