worker-automate-hub 0.5.749__py3-none-any.whl → 0.5.912__py3-none-any.whl

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 (36) hide show
  1. worker_automate_hub/api/client.py +186 -68
  2. worker_automate_hub/api/rpa_historico_service.py +1 -0
  3. worker_automate_hub/cli.py +91 -111
  4. worker_automate_hub/tasks/jobs/abertura_livros_fiscais.py +112 -229
  5. worker_automate_hub/tasks/jobs/descartes.py +91 -77
  6. worker_automate_hub/tasks/jobs/devolucao_produtos.py +1386 -0
  7. worker_automate_hub/tasks/jobs/entrada_de_notas_15.py +3 -46
  8. worker_automate_hub/tasks/jobs/entrada_de_notas_22.py +833 -0
  9. worker_automate_hub/tasks/jobs/entrada_de_notas_36.py +29 -9
  10. worker_automate_hub/tasks/jobs/entrada_de_notas_37.py +619 -0
  11. worker_automate_hub/tasks/jobs/entrada_de_notas_39.py +1 -1
  12. worker_automate_hub/tasks/jobs/entrada_de_notas_9.py +63 -16
  13. worker_automate_hub/tasks/jobs/extracao_dados_nielsen.py +504 -0
  14. worker_automate_hub/tasks/jobs/extracao_saldo_estoque.py +242 -108
  15. worker_automate_hub/tasks/jobs/extracao_saldo_estoque_fiscal.py +688 -0
  16. worker_automate_hub/tasks/jobs/fidc_gerar_nosso_numero.py +2 -2
  17. worker_automate_hub/tasks/jobs/fidc_remessa_cobranca_cnab240.py +25 -16
  18. worker_automate_hub/tasks/jobs/geracao_balancetes_filial.py +330 -0
  19. worker_automate_hub/tasks/jobs/importacao_extratos.py +538 -0
  20. worker_automate_hub/tasks/jobs/importacao_extratos_748.py +800 -0
  21. worker_automate_hub/tasks/jobs/inclusao_pedidos_ipiranga.py +222 -0
  22. worker_automate_hub/tasks/jobs/inclusao_pedidos_raizen.py +174 -0
  23. worker_automate_hub/tasks/jobs/inclusao_pedidos_vibra.py +327 -0
  24. worker_automate_hub/tasks/jobs/notas_faturamento_sap.py +438 -157
  25. worker_automate_hub/tasks/jobs/opex_capex.py +540 -326
  26. worker_automate_hub/tasks/jobs/sped_fiscal.py +8 -8
  27. worker_automate_hub/tasks/jobs/transferencias.py +52 -41
  28. worker_automate_hub/tasks/task_definitions.py +46 -1
  29. worker_automate_hub/tasks/task_executor.py +11 -0
  30. worker_automate_hub/utils/util.py +252 -215
  31. worker_automate_hub/utils/utils_nfe_entrada.py +1 -1
  32. worker_automate_hub/worker.py +1 -9
  33. {worker_automate_hub-0.5.749.dist-info → worker_automate_hub-0.5.912.dist-info}/METADATA +4 -2
  34. {worker_automate_hub-0.5.749.dist-info → worker_automate_hub-0.5.912.dist-info}/RECORD +36 -25
  35. {worker_automate_hub-0.5.749.dist-info → worker_automate_hub-0.5.912.dist-info}/WHEEL +1 -1
  36. {worker_automate_hub-0.5.749.dist-info → worker_automate_hub-0.5.912.dist-info}/entry_points.txt +0 -0
@@ -12,11 +12,13 @@ import win32clipboard
12
12
  from PIL import Image, ImageEnhance
13
13
  from pywinauto.application import Application
14
14
  from pywinauto.keyboard import send_keys
15
- from pywinauto.timings import wait_until
15
+ from pywinauto.timings import TimeoutError as PywTimeout, wait_until
16
16
  from pywinauto_recorder.player import set_combobox
17
17
  from rich.console import Console
18
18
  import sys
19
19
  import asyncio
20
+ from pywinauto import Desktop
21
+
20
22
  sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..","..","..")))
21
23
  from worker_automate_hub.api.ahead_service import save_xml_to_downloads
22
24
  from worker_automate_hub.api.client import (
@@ -61,7 +63,11 @@ pyautogui.PAUSE = 0.5
61
63
  pyautogui.FAILSAFE = False
62
64
  console = Console()
63
65
 
66
+ BASE_PATH = r"assets\entrada_notas"
67
+
68
+
64
69
  async def get_ultimo_item():
70
+ console.print("[ITENS] Iniciando função get_ultimo_item...", style="bold cyan")
65
71
  send_keys("^({END})")
66
72
  await worker_sleep(2)
67
73
  send_keys("+{F10}")
@@ -70,133 +76,145 @@ async def get_ultimo_item():
70
76
  await worker_sleep(1)
71
77
  send_keys("{ENTER}")
72
78
  await worker_sleep(2)
79
+ console.print("[ITENS] Conectando na janela 'Alteração de Item' para obter último índice...", style="cyan")
73
80
  app = Application().connect(title="Alteração de Item")
74
81
  main_window = app["Alteração de Item"]
75
82
  main_window.set_focus()
76
83
  edit = main_window.child_window(class_name="TDBIEditCode", found_index=0)
77
84
  index_ultimo_item = int(edit.window_text())
85
+ console.print(f"[ITENS] Último item encontrado: {index_ultimo_item}", style="bold green")
78
86
  try:
79
87
  btn_cancelar = main_window.child_window(title="&Cancelar")
80
88
  btn_cancelar.click()
81
89
  except Exception as error:
82
90
  btn_cancelar = main_window.child_window(title="Cancelar")
83
91
  btn_cancelar.click()
84
- console.print(f"Erro ao realizar get_ultimo_item: {error}")
92
+ console.print(f"[ITENS] Erro ao fechar janela get_ultimo_item: {error}", style="bold yellow")
85
93
  await worker_sleep(1)
86
94
  return index_ultimo_item
87
95
 
88
- async def opex_capex(task: RpaProcessoEntradaDTO) -> RpaRetornoProcessoDTO:
89
- """
90
- Processo que realiza entrada de notas no ERP EMSys(Linx).
91
96
 
92
- """
97
+ async def opex_capex(task: RpaProcessoEntradaDTO) -> RpaRetornoProcessoDTO:
98
+ numero_nota = None
93
99
  try:
94
- # Get config from BOF
100
+ console.print("\n================ INÍCIO PROCESSO opex_capex ================\n", style="bold blue")
101
+ console.print(f"[TASK] Dados da task recebida: {task}", style="cyan")
102
+
103
+ console.print("[ETAPA 1] Buscando configuração de login_emsys via API...", style="bold cyan")
95
104
  config = await get_config_by_name("login_emsys")
96
- console.print(task)
105
+ console.print("[ETAPA 1] Configuração 'login_emsys' obtida com sucesso.", style="bold green")
97
106
 
98
- # Seta config entrada na var nota para melhor entendimento
99
107
  nota = task.configEntrada
108
+ console.print(f"[ETAPA 1] ConfigEntrada (nota): {nota}", style="cyan")
109
+
100
110
  multiplicador_timeout = int(float(task.sistemas[0].timeout))
111
+ console.print(f"[ETAPA 1] Timeout multiplicador definido como: {multiplicador_timeout}", style="cyan")
101
112
  set_variable("timeout_multiplicador", multiplicador_timeout)
102
113
 
103
- # Fecha a instancia do emsys - caso esteja aberta
114
+ console.print("[ETAPA 2] Fechando instâncias do EMSys se existirem...", style="bold cyan")
104
115
  await kill_all_emsys()
105
116
  data_atual = datetime.now().strftime("%d/%m/%Y")
106
- print(data_atual)
107
- # Buscar número da nota
117
+ console.print(f"[ETAPA 2] Data atual: {data_atual}", style="cyan")
118
+
119
+ console.print("[ETAPA 3] Preparando dados da nota para consulta na API...", style="bold cyan")
108
120
  numero_nota = nota.get("numeroNota")
109
121
  serie_nota = nota.get("serieNota")
110
- filial_nota = nota.get("descricaoFilial")
111
- filial_nota = filial_nota.split("-")[0].strip()
122
+ fornecedor = nota.get("fornecedorCnpj")
112
123
  centro_custo = nota.get("centroCusto")
113
124
  centro_custo = centro_custo.split("-")[0].strip().lstrip("0")
114
125
 
126
+ console.print(f"[ETAPA 3] NumeroNota={numero_nota} | Serie={serie_nota} | FornecedorCNPJ={fornecedor} | CentroCusto={centro_custo}", style="cyan")
127
+
115
128
  try:
129
+ console.print("[ETAPA 4] Consultando dados da NF no EMSys via get_dados_nf_emsys...", style="bold cyan")
116
130
  dados_nf = await get_dados_nf_emsys(
117
131
  numero_nota=numero_nota,
118
132
  serie_nota=serie_nota,
119
- filial_nota=filial_nota
133
+ fornecedor=fornecedor
120
134
  )
135
+ console.print(f"[ETAPA 4] Retorno get_dados_nf_emsys: {dados_nf}", style="cyan")
121
136
 
122
- # Se a API retornou erro
123
137
  if isinstance(dados_nf, dict) and "erro" in dados_nf:
124
- console.print("Erro retornado pela API:", dados_nf["erro"])
138
+ console.print("[ETAPA 4] Erro retornado pela API de dados NF.", style="bold red")
139
+ console.print(f"[ETAPA 4] Detalhes erro API: {dados_nf['erro']}", style="red")
125
140
  nf_chave_acesso = None
126
-
127
- # Se retornou lista mas está vazia
128
141
  elif isinstance(dados_nf, list) and not dados_nf:
129
- console.print("Nenhum dado encontrado para a nota.")
142
+ console.print("[ETAPA 4] Nenhum dado encontrado para a nota na API.", style="bold yellow")
130
143
  nf_chave_acesso = None
131
-
132
- # Se retornou lista com dados
133
144
  else:
134
145
  nf_chave_acesso = dados_nf[0].get("chaveNfe")
135
- console.print("Chave da NF:", nf_chave_acesso)
146
+ console.print(f"[ETAPA 4] Chave da NF obtida: {nf_chave_acesso}", style="bold green")
136
147
 
137
148
  except Exception as e:
138
- console.print("Erro inesperado ao buscar nota:", str(e))
139
- nf_chave_acesso = None
149
+ observacao = f"[ERRO ETAPA 4] Erro ao buscar nota via get_dados_nf_emsys: {e}"
150
+ console.print(observacao, style="bold red")
151
+ logger.error(observacao)
152
+ return RpaRetornoProcessoDTO(
153
+ sucesso=False,
154
+ retorno=observacao,
155
+ status=RpaHistoricoStatusEnum.Falha,
156
+ tags=[RpaTagDTO(descricao=RpaTagEnum.Negocio)]
157
+ )
140
158
 
141
- # Download XML
142
- console.log("Realizando o download do XML..\n")
159
+ console.print("[ETAPA 5] Iniciando download do XML da NF...", style="bold cyan")
143
160
  await save_xml_to_downloads(nf_chave_acesso)
161
+ console.print("[ETAPA 5] XML baixado com sucesso.", style="bold green")
144
162
 
163
+ console.print("[ETAPA 6] Consultando status da NF no EMSys via get_status_nf_emsys...", style="bold cyan")
145
164
  status_nf_emsys = await get_status_nf_emsys(nf_chave_acesso)
165
+ console.print(f"[ETAPA 6] Status NF EMSys: {status_nf_emsys}", style="cyan")
146
166
 
147
167
  empresa_codigo = dados_nf[0]["empresaCodigo"]
148
168
  cfop = dados_nf[0]["numeroDoCfop"]
149
169
  cfops_itens = [item["cfopProduto"] for item in dados_nf[0]["itens"]]
170
+ console.print(f"[ETAPA 6] EmpresaCodigo={empresa_codigo} | CFOP NF={cfop} | CFOPs Itens={cfops_itens}", style="cyan")
150
171
 
151
-
152
-
153
172
  if status_nf_emsys.get("status") == "Lançada":
154
- console.print(
155
- "\\Nota fiscal já lançada, processo finalizado...", style="bold green"
156
- )
173
+ console.print("\\Nota fiscal já lançada, processo finalizado...", style="bold green")
157
174
  return RpaRetornoProcessoDTO(
158
175
  sucesso=False,
159
176
  retorno="Nota fiscal já lançada",
160
177
  status=RpaHistoricoStatusEnum.Descartado,
161
178
  )
162
179
  else:
163
- console.print("\\Nota fiscal não lançada, iniciando o processo...")
180
+ console.print("\\Nota fiscal não lançada, iniciando o processo...", style="yellow")
164
181
 
182
+ console.print("[ETAPA 7] Iniciando EMSys3_29.exe...", style="bold cyan")
165
183
  app = Application(backend="win32").start("C:\\Rezende\\EMSys3\\EMSys3_29.exe")
166
184
  warnings.filterwarnings(
167
185
  "ignore",
168
186
  category=UserWarning,
169
- message="32-bit application should be automated using 32-bit Python",
187
+ message="32-bit application should be automated usando 32-bit Python",
170
188
  )
171
- console.print("\nEMSys iniciando...", style="bold green")
172
- return_login = await login_emsys(config.conConfiguracao, app, task, filial_origem = empresa_codigo)
189
+ console.print("[ETAPA 7] EMSys iniciando...", style="bold green")
190
+
191
+ console.print("[ETAPA 7] Realizando login no EMSys pelo login_emsys...", style="bold cyan")
192
+ return_login = await login_emsys(config.conConfiguracao, app, task, filial_origem=empresa_codigo)
173
193
 
174
- if return_login.sucesso == True:
194
+ if return_login.sucesso:
195
+ console.print("[ETAPA 8] Login realizado com sucesso. Acessando menu 'Nota Fiscal de Entrada'...", style="bold green")
175
196
  type_text_into_field(
176
197
  "Nota Fiscal de Entrada", app["TFrmMenuPrincipal"]["Edit"], True, "50"
177
198
  )
178
199
  pyautogui.press("enter")
179
200
  await worker_sleep(2)
180
201
  pyautogui.press("enter")
181
- console.print(
182
- f"\nPesquisa: 'Nota Fiscal de Entrada' realizada com sucesso",
183
- style="bold green",
184
- )
202
+ console.print("[ETAPA 8] Pesquisa: 'Nota Fiscal de Entrada' realizada com sucesso", style="bold green")
185
203
  else:
186
- logger.info(f"\nError Message: {return_login.retorno}")
187
- console.print(f"\nError Message: {return_login.retorno}", style="bold red")
204
+ logger.info(f"[ETAPA 8] Error Message login: {return_login.retorno}")
205
+ console.print(f"[ETAPA 8] Error Message login: {return_login.retorno}", style="bold red")
188
206
  return return_login
189
207
 
190
208
  await worker_sleep(6)
191
209
 
192
- # Procura campo documento
193
- console.print("Navegando pela Janela de Nota Fiscal de Entrada...\n")
210
+ console.print("[ETAPA 9] Selecionando tipo de documento: NOTA FISCAL DE ENTRADA ELETRONICA - DANFE...", style="bold cyan")
194
211
  document_type = await select_documento_type(
195
212
  "NOTA FISCAL DE ENTRADA ELETRONICA - DANFE"
196
213
  )
197
- if document_type.sucesso == True:
214
+ if document_type.sucesso:
198
215
  console.log(document_type.retorno, style="bold green")
199
216
  else:
217
+ console.print("[ETAPA 9] Falha ao selecionar tipo de documento.", style="bold red")
200
218
  return RpaRetornoProcessoDTO(
201
219
  sucesso=False,
202
220
  retorno=document_type.retorno,
@@ -206,11 +224,12 @@ async def opex_capex(task: RpaProcessoEntradaDTO) -> RpaRetornoProcessoDTO:
206
224
 
207
225
  await worker_sleep(4)
208
226
 
209
- # Clica em 'Importar-Nfe'
227
+ console.print("[ETAPA 10] Iniciando importação da NFe (XML)...", style="bold cyan")
210
228
  imported_nfe = await import_nfe()
211
- if imported_nfe.sucesso == True:
229
+ if imported_nfe.sucesso:
212
230
  console.log(imported_nfe.retorno, style="bold green")
213
231
  else:
232
+ console.print("[ETAPA 10] Falha na importação da NFe.", style="bold red")
214
233
  return RpaRetornoProcessoDTO(
215
234
  sucesso=False,
216
235
  retorno=imported_nfe.retorno,
@@ -220,18 +239,21 @@ async def opex_capex(task: RpaProcessoEntradaDTO) -> RpaRetornoProcessoDTO:
220
239
 
221
240
  await worker_sleep(5)
222
241
 
242
+ console.print("[ETAPA 11] Buscando XML importado no EMSys via get_xml...", style="bold cyan")
223
243
  await get_xml(nf_chave_acesso)
244
+ console.print("[ETAPA 11] get_xml concluído.", style="bold green")
224
245
 
246
+ await worker_sleep(10)
225
247
 
226
- await worker_sleep(3)
227
-
228
- # VERIFICANDO A EXISTENCIA DE WARNINGS
248
+ console.print("[ETAPA 12] Verificando existência de pop-up 'Warning' após importação do XML...", style="bold cyan")
229
249
  warning_pop_up = await is_window_open("Warning")
230
- if warning_pop_up["IsOpened"] == True:
250
+ if warning_pop_up["IsOpened"]:
251
+ console.print("[ETAPA 12] Pop-up Warning encontrado, tratando via warnings_after_xml_imported...", style="yellow")
231
252
  warning_work = await warnings_after_xml_imported()
232
- if warning_work.sucesso == True:
253
+ if warning_work.sucesso:
233
254
  console.log(warning_work.retorno, style="bold green")
234
255
  else:
256
+ console.print("[ETAPA 12] Falha ao tratar Warning após XML.", style="bold red")
235
257
  return RpaRetornoProcessoDTO(
236
258
  sucesso=False,
237
259
  retorno=warning_work.retorno,
@@ -239,9 +261,10 @@ async def opex_capex(task: RpaProcessoEntradaDTO) -> RpaRetornoProcessoDTO:
239
261
  tags=[RpaTagDTO(descricao=RpaTagEnum.Tecnico)]
240
262
  )
241
263
 
242
- # VERIFICANDO A EXISTENCIA DE ERRO
264
+ console.print("[ETAPA 13] Verificando existência de pop-up 'Erro' após importação do XML...", style="bold cyan")
243
265
  erro_pop_up = await is_window_open("Erro")
244
- if erro_pop_up["IsOpened"] == True:
266
+ if erro_pop_up["IsOpened"]:
267
+ console.print("[ETAPA 13] Pop-up Erro encontrado, tratando via error_after_xml_imported...", style="bold red")
245
268
  error_work = await error_after_xml_imported()
246
269
  return RpaRetornoProcessoDTO(
247
270
  sucesso=error_work.sucesso,
@@ -249,21 +272,16 @@ async def opex_capex(task: RpaProcessoEntradaDTO) -> RpaRetornoProcessoDTO:
249
272
  status=error_work.status,
250
273
  tags=error_work.tags
251
274
  )
275
+
276
+ await worker_sleep(3)
252
277
 
253
- app = Application().connect(
254
- title="Informações para importação da Nota Fiscal Eletrônica"
255
- )
278
+ console.print("[ETAPA 14] Conectando na janela 'Informações para importação da Nota Fiscal Eletrônica'...", style="bold cyan")
279
+ app = Application().connect(title="Informações para importação da Nota Fiscal Eletrônica")
256
280
  main_window = app["Informações para importação da Nota Fiscal Eletrônica"]
257
281
 
258
- # INTERAGINDO COM A NATUREZA DA OPERACAO
259
- console.print(f"Inserindo a informação da CFOP: {cfop} ...\n")
260
- combo_box_natureza_operacao = main_window.child_window(
261
- class_name="TDBIComboBox", found_index=0
262
- )
263
- combo_box_natureza_operacao.click()
282
+ # ================= BLOCO CFOP =================
283
+ console.print(f"[CFOP] Iniciando processo de seleção da Natureza de Operação (CFOP: {cfop})...", style="bold cyan")
264
284
 
265
- await worker_sleep(3)
266
- # Mapeamento CFOP -> (lista, código exibido no combobox)
267
285
  cfop_map = {
268
286
  "1556": (['5101', '5102', '5103', '5104'], "1.556"),
269
287
  "1407": (['5401', '5403', '5404', '5405'], "1.407"),
@@ -271,51 +289,105 @@ async def opex_capex(task: RpaProcessoEntradaDTO) -> RpaRetornoProcessoDTO:
271
289
  }
272
290
 
273
291
  cfop_str = str(cfop)
292
+ cfop_key_escolhido = None
293
+ codigo_combo_escolhido = None
294
+
274
295
  for key, (lista, codigo_combo) in cfop_map.items():
275
296
  if cfop_str in lista:
297
+ cfop_key_escolhido = key
298
+ codigo_combo_escolhido = codigo_combo
299
+ break
300
+
301
+ console.print(f"[CFOP] CFOP NF: {cfop_str} | CFOP key escolhida: {cfop_key_escolhido} | Código combo: {codigo_combo_escolhido}", style="cyan")
302
+
303
+ if not cfop_key_escolhido:
304
+ msg = "Erro mapeado, CFOP diferente de início com 540 ou 510, necessário ação manual ou ajuste no robô..."
305
+ console.print(f"[CFOP] {msg}", style="bold red")
306
+ return RpaRetornoProcessoDTO(
307
+ sucesso=False,
308
+ retorno=msg,
309
+ status=RpaHistoricoStatusEnum.Falha,
310
+ tags=[RpaTagDTO(descricao=RpaTagEnum.Negocio)]
311
+ )
312
+
313
+ max_tentativas_cfop = 3
314
+ selecionou_cfop = False
315
+
316
+ for tentativa in range(1, max_tentativas_cfop + 1):
317
+ try:
318
+ console.print(f"[CFOP] Tentando selecionar Natureza de Operação (tentativa {tentativa}/{max_tentativas_cfop})...", style="bold cyan")
319
+
320
+ combo_box_natureza_operacao = main_window.child_window(
321
+ class_name="TDBIComboBox", found_index=0
322
+ )
323
+
324
+ combo_box_natureza_operacao.set_focus()
325
+ combo_box_natureza_operacao.click_input()
326
+ await worker_sleep(1)
327
+
328
+ texto_alvo_parcial = f"{cfop_key_escolhido}-COMPRA DE MERCADORIAS SEM ESTOQUE"
329
+ texto_alvo_codigo = str(codigo_combo_escolhido)
330
+
331
+ console.print(f"[CFOP] Buscando opção que contenha '{texto_alvo_parcial}' e '{texto_alvo_codigo}'...", style="cyan")
332
+
276
333
  for opc in combo_box_natureza_operacao.item_texts():
277
- if (f"{key}-COMPRA DE MERCADORIAS SEM ESTOQUE" in opc
278
- and str(codigo_combo) in opc):
334
+ if (texto_alvo_parcial in opc) and (texto_alvo_codigo in opc):
335
+ console.print(f"[CFOP] Opção candidata encontrada: {opc}", style="cyan")
279
336
  combo_box_natureza_operacao.select(opc)
280
337
  send_keys("{ENTER}")
281
- break
282
- break
338
+ await worker_sleep(1)
283
339
 
284
- else:
285
- console.print(
286
- "Erro mapeado, CFOP diferente de início com 540 ou 510, necessário ação manual ou ajuste no robô...\n"
287
- )
340
+ texto_final = combo_box_natureza_operacao.window_text().strip()
341
+ console.print(f"[CFOP] Texto final no combo: '{texto_final}'", style="cyan")
342
+ if texto_alvo_codigo in texto_final or cfop_key_escolhido in texto_final:
343
+ selecionou_cfop = True
344
+ console.print(f"[CFOP] Natureza de Operação selecionada com sucesso: {texto_final}", style="bold green")
345
+ break
346
+
347
+ if selecionou_cfop:
348
+ break
349
+ else:
350
+ console.print("[CFOP] Não foi possível confirmar a seleção da Natureza de Operação. Tentando novamente...", style="yellow")
351
+ await worker_sleep(2)
352
+
353
+ except Exception as e:
354
+ console.print(f"[CFOP] Erro ao selecionar Natureza de Operação na tentativa {tentativa}: {e}", style="bold red")
355
+ await worker_sleep(2)
356
+
357
+ if not selecionou_cfop:
358
+ msg = "Não foi possível selecionar a Natureza de Operação (CFOP) após múltiplas tentativas."
359
+ console.print(f"[CFOP] {msg}", style="bold red")
288
360
  return RpaRetornoProcessoDTO(
289
361
  sucesso=False,
290
- retorno="Erro mapeado, CFOP diferente de início com 540 ou 510, necessário ação manual ou ajuste no robô.",
362
+ retorno=msg,
291
363
  status=RpaHistoricoStatusEnum.Falha,
292
- tags=[RpaTagDTO(descricao=RpaTagEnum.Negocio)]
364
+ tags=[RpaTagDTO(descricao=RpaTagEnum.Tecnico)]
293
365
  )
294
-
366
+
367
+ console.print(f"[CFOP] CFOP selecionado com base em {cfop_key_escolhido}. CFOP original da NF: {cfop}", style="bold green")
368
+
295
369
  await worker_sleep(3)
296
370
 
297
- # INTERAGINDO COM O CAMPO ALMOXARIFADO
298
- fornecedor = dados_nf[0]["fornecedorNome"]
371
+ # ================= ALMOXARIFADO =================
372
+ console.print("[ALMOXARIFADO] Iniciando preenchimento do almoxarifado...", style="bold cyan")
373
+ fornecedor_nome = dados_nf[0]["fornecedorNome"]
299
374
  empresaCodigo = dados_nf[0]["empresaCodigo"]
300
- console.print(
301
- f"Inserindo a informação do Almoxarifado {empresaCodigo} ...\n"
302
- )
375
+ console.print(f"[ALMOXARIFADO] Fornecedor: {fornecedor_nome} | EmpresaCodigo: {empresaCodigo}", style="cyan")
376
+ console.print(f"[ALMOXARIFADO] Inserindo informação do Almoxarifado para empresa_codigo={empresa_codigo}...", style="cyan")
303
377
  try:
304
- new_app = Application(backend="uia").connect(
305
- title="Informações para importação da Nota Fiscal Eletrônica"
306
- )
378
+ new_app = Application(backend="uia").connect(title="Informações para importação da Nota Fiscal Eletrônica")
307
379
  window = new_app["Informações para importação da Nota Fiscal Eletrônica"]
308
- edit = window.child_window(
309
- class_name="TDBIEditCode", found_index=3, control_type="Edit"
310
- )
380
+ edit = window.child_window(class_name="TDBIEditCode", found_index=3, control_type="Edit")
311
381
  if empresa_codigo == '1':
312
382
  valor_almoxarifado = empresaCodigo + "60"
313
383
  else:
314
384
  valor_almoxarifado = empresaCodigo + "50"
385
+ console.print(f"[ALMOXARIFADO] Valor a ser inserido no almoxarifado: {valor_almoxarifado}", style="cyan")
315
386
  edit.set_edit_text(valor_almoxarifado)
316
387
  edit.type_keys("{TAB}")
388
+ console.print("[ALMOXARIFADO] Almoxarifado preenchido com sucesso.", style="bold green")
317
389
  except Exception as e:
318
- console.print(f"Erro ao iterar itens de almoxarifado: {e}")
390
+ console.print(f"[ALMOXARIFADO] Erro ao iterar itens de almoxarifado: {e}", style="bold red")
319
391
  return RpaRetornoProcessoDTO(
320
392
  sucesso=False,
321
393
  retorno=f"Erro ao iterar itens de almoxarifado: {e}",
@@ -323,14 +395,19 @@ async def opex_capex(task: RpaProcessoEntradaDTO) -> RpaRetornoProcessoDTO:
323
395
  tags=[RpaTagDTO(descricao=RpaTagEnum.Tecnico)]
324
396
  )
325
397
 
326
- await worker_sleep(1)
327
- console.print("Inserir conta contábil")
398
+ await worker_sleep(3)
399
+
400
+ # ================= DESPESA =================
401
+ console.print("[DESPESA] Inserindo conta contábil / tipo de despesa...", style="bold cyan")
328
402
  despesa = nota.get('contaContabil')
403
+ console.print(f"[DESPESA] Conta contábil original: {despesa}", style="cyan")
329
404
  despesa = despesa.split("-")[0].strip()
405
+ console.print(f"[DESPESA] Conta contábil tratada (apenas código): {despesa}", style="cyan")
330
406
  tipo_despesa_work = await tipo_despesa(despesa)
331
- if tipo_despesa_work.sucesso == True:
407
+ if tipo_despesa_work.sucesso:
332
408
  console.log(tipo_despesa_work.retorno, style="bold green")
333
409
  else:
410
+ console.print("[DESPESA] Falha na função tipo_despesa.", style="bold red")
334
411
  return RpaRetornoProcessoDTO(
335
412
  sucesso=False,
336
413
  retorno=tipo_despesa_work.retorno,
@@ -340,16 +417,12 @@ async def opex_capex(task: RpaProcessoEntradaDTO) -> RpaRetornoProcessoDTO:
340
417
  await worker_sleep(5)
341
418
 
342
419
  try:
343
- console.print("Verificando se existe o tipo de despesa...")
344
- # Conectar à aplicação
345
- app = Application(backend="win32").connect(class_name="TFrmBuscaGeralDialog")
346
-
347
- # Acessar a janela buscar
348
- janela = app.window(class_name="TFrmBuscaGeralDialog")
420
+ console.print("[DESPESA] Verificando se existe tela de busca de tipo de despesa (TFrmBuscaGeralDialog)...", style="bold cyan")
421
+ app_busca = Application(backend="win32").connect(class_name="TFrmBuscaGeralDialog")
422
+ janela = app_busca.window(class_name="TFrmBuscaGeralDialog")
349
423
  janela.set_focus()
350
- # Clicar em canelar
351
424
  janela.child_window(title="&Cancelar", class_name="TBitBtn").click()
352
- console.print("Tipo de despesa não encontrado")
425
+ console.print("[DESPESA] Tela de busca de tipo de despesa encontrada. Tipo de despesa não localizado.", style="yellow")
353
426
  return RpaRetornoProcessoDTO(
354
427
  sucesso=False,
355
428
  retorno="Tipo de Despesa / conta contábil não localizado",
@@ -357,12 +430,18 @@ async def opex_capex(task: RpaProcessoEntradaDTO) -> RpaRetornoProcessoDTO:
357
430
  tags=[RpaTagDTO(descricao=RpaTagEnum.Negocio)]
358
431
  )
359
432
  except:
433
+ console.print("[DESPESA] Tela de busca de tipo de despesa não apareceu. Seguindo fluxo normalmente.", style="cyan")
360
434
  pass
361
- # INTERAGINDO COM O CHECKBOX ZERAR ICMS
435
+
436
+ await worker_sleep(3)
437
+
438
+ # ================= ICMS HEADER =================
439
+ console.print("[ICMS] Ativando checkbox 'Zerar ICMS'...", style="bold cyan")
362
440
  checkbox_zerar_icms = await zerar_icms()
363
- if checkbox_zerar_icms.sucesso == True:
441
+ if checkbox_zerar_icms.sucesso:
364
442
  console.log(checkbox_zerar_icms.retorno, style="bold green")
365
443
  else:
444
+ console.print("[ICMS] Falha na função zerar_icms.", style="bold red")
366
445
  return RpaRetornoProcessoDTO(
367
446
  sucesso=False,
368
447
  retorno=checkbox_zerar_icms.retorno,
@@ -370,15 +449,17 @@ async def opex_capex(task: RpaProcessoEntradaDTO) -> RpaRetornoProcessoDTO:
370
449
  tags=[RpaTagDTO(descricao=RpaTagEnum.Tecnico)]
371
450
  )
372
451
 
373
- # INTERAGINDO COM O CAMPO DE CODIGO DO ICMS
374
- if key =='1556':
452
+ console.print("[ICMS] Definindo código ICMS conforme CFOP mapeado...", style="bold cyan")
453
+ if cfop_key_escolhido == '1556':
375
454
  codigo_icms = '33'
376
455
  else:
377
456
  codigo_icms = '20'
457
+ console.print(f"[ICMS] Código ICMS escolhido: {codigo_icms}", style="cyan")
378
458
  cod_icms_work = await cod_icms(codigo_icms)
379
- if cod_icms_work.sucesso == True:
459
+ if cod_icms_work.sucesso:
380
460
  console.log(cod_icms_work.retorno, style="bold green")
381
461
  else:
462
+ console.print("[ICMS] Falha na função cod_icms.", style="bold red")
382
463
  return RpaRetornoProcessoDTO(
383
464
  sucesso=False,
384
465
  retorno=cod_icms_work.retorno,
@@ -386,80 +467,81 @@ async def opex_capex(task: RpaProcessoEntradaDTO) -> RpaRetornoProcessoDTO:
386
467
  tags=[RpaTagDTO(descricao=RpaTagEnum.Tecnico)]
387
468
  )
388
469
 
389
- # INTERAGINDO COM O CAMPO Manter Natureza de Operação selecionada
390
- console.print(
391
- f"Selecionando a opção 'Manter Natureza de Operação selecionada'...\n"
392
- )
470
+ await worker_sleep(3)
471
+
472
+ console.print("[CFOP] Selecionando a opção 'Manter Natureza de Operação selecionada'...", style="bold cyan")
393
473
  checkbox = window.child_window(
394
474
  title="Manter Natureza de Operação selecionada",
395
475
  class_name="TDBICheckBox",
396
476
  )
397
477
  if not checkbox.get_toggle_state() == 1:
398
478
  checkbox.click()
399
- console.print(
400
- "A opção 'Manter Natureza de Operação selecionada' selecionado com sucesso... \n"
401
- )
479
+ console.print("[CFOP] Opção 'Manter Natureza de Operação selecionada' marcada com sucesso.", style="bold green")
480
+ else:
481
+ console.print("[CFOP] Opção 'Manter Natureza de Operação selecionada' já estava marcada.", style="cyan")
402
482
 
403
- await worker_sleep(2)
404
- console.print("Clicando em OK... \n")
483
+ await worker_sleep(3)
484
+ console.print("[CFOP] Clicando em OK para confirmar informações da importação...", style="bold cyan")
405
485
 
406
486
  max_attempts = 3
407
487
  i = 0
408
488
  while i < max_attempts:
409
- console.print("Clicando no botão de OK...\n")
489
+ console.print(f"[CFOP] Tentativa {i+1}/{max_attempts} de clicar no botão OK...", style="cyan")
410
490
  try:
411
491
  try:
412
492
  btn_ok = main_window.child_window(title="Ok")
413
493
  btn_ok.click()
494
+ console.print("[CFOP] Clique no botão 'Ok' realizado.", style="cyan")
414
495
  except:
415
496
  btn_ok = main_window.child_window(title="&Ok")
416
497
  btn_ok.click()
498
+ console.print("[CFOP] Clique no botão '&Ok' realizado.", style="cyan")
417
499
  except:
418
- console.print("Não foi possivel clicar no Botão OK... \n")
500
+ console.print("[CFOP] Não foi possível clicar no botão OK nesta tentativa.", style="yellow")
419
501
 
420
502
  await worker_sleep(3)
421
503
 
422
- console.print(
423
- "Verificando a existencia da tela Informações para importação da Nota Fiscal Eletrônica...\n"
424
- )
425
-
426
504
  try:
427
505
  informacao_nf_eletronica = await is_window_open(
428
506
  "Informações para importação da Nota Fiscal Eletrônica"
429
507
  )
430
508
  if not informacao_nf_eletronica["IsOpened"]:
431
- console.print(
432
- "Tela Informações para importação da Nota Fiscal Eletrônica fechada, seguindo com o processo"
433
- )
509
+ console.print("[CFOP] Tela de Informações para importação fechada. Prosseguindo...", style="bold green")
434
510
  break
511
+ else:
512
+ console.print("[CFOP] Tela ainda aberta após clique em OK.", style="yellow")
435
513
  except Exception as e:
436
- console.print(
437
- f"Tela Informações para importação da Nota Fiscal Eletrônica encontrada. Tentativa {i + 1}/{max_attempts}."
438
- )
514
+ console.print(f"[CFOP] Erro ao verificar tela de informações: {e}. Tentativa {i+1}/{max_attempts}.", style="bold red")
439
515
 
440
516
  i += 1
441
517
 
442
518
  if i == max_attempts:
519
+ msg = "Número máximo de tentativas atingido, Não foi possivel finalizar os trabalhos na tela de Informações para importação da Nota Fiscal Eletrônica"
520
+ console.print(f"[CFOP] {msg}", style="bold red")
443
521
  return RpaRetornoProcessoDTO(
444
522
  sucesso=False,
445
- retorno="Número máximo de tentativas atingido, Não foi possivel finalizar os trabalhos na tela de Informações para importação da Nota Fiscal Eletrônica",
523
+ retorno=msg,
446
524
  status=RpaHistoricoStatusEnum.Falha,
447
525
  tags=[RpaTagDTO(descricao=RpaTagEnum.Tecnico)]
448
526
  )
449
527
 
450
528
  await worker_sleep(10)
451
529
 
530
+ # ================= ITENS =================
531
+ console.print("[ITENS] Verificando pop-up de itens não localizados / NCM...", style="bold cyan")
452
532
  try:
453
- console.print("Verificando itens não localizados ou NCM...\n")
454
533
  itens_by_supplier = await is_window_open_by_class("TFrmAguarde", "TMessageForm")
534
+ console.print(f"[ITENS] Retorno is_window_open_by_class: {itens_by_supplier}", style="cyan")
455
535
 
456
- if itens_by_supplier["IsOpened"] == True:
536
+ if itens_by_supplier["IsOpened"]:
537
+ console.print("[ITENS] Pop-up de itens não localizados encontrado. Chamando itens_not_found_supplier...", style="yellow")
457
538
  itens_by_supplier_work = await itens_not_found_supplier(nota.get("nfe"))
458
-
459
539
  if not itens_by_supplier_work.sucesso:
540
+ console.print("[ITENS] Tratativa de itens não localizados retornou falha.", style="bold red")
460
541
  return itens_by_supplier_work
461
542
 
462
543
  except Exception as error:
544
+ console.print(f"[ITENS] Falha ao verificar POP-UP de itens não localizados: {error}", style="bold red")
463
545
  return RpaRetornoProcessoDTO(
464
546
  sucesso=False,
465
547
  retorno=f"Falha ao verificar a existência de POP-UP de itens não localizados: {error}",
@@ -469,30 +551,35 @@ async def opex_capex(task: RpaProcessoEntradaDTO) -> RpaRetornoProcessoDTO:
469
551
 
470
552
  await worker_sleep(10)
471
553
 
472
- # Clicar em itens da nota
473
- imagem = r"C:\Users\automatehub\Documents\GitHub\worker-automate-hub\worker_automate_hub\assets\entrada_notas\intens_nota.png"
474
-
475
- # Tenta localizar a imagem na tela
554
+ console.print("[ITENS] Localizando botão 'Itens da Nota' via imagem...", style="bold cyan")
555
+ imagem_itens = fr"{BASE_PATH}\itens_nota.png"
556
+ tentativas_img = 0
476
557
  while True:
477
- local = pyautogui.locateCenterOnScreen(imagem, confidence=0.8) # 0.8 = 80% de precisão
558
+ tentativas_img += 1
559
+ console.print(f"[ITENS] Tentativa {tentativas_img} de localizar itens_nota.png...", style="cyan")
560
+ local = pyautogui.locateCenterOnScreen(imagem_itens, confidence=0.8)
478
561
  if local:
479
- pyautogui.click(local) # Clica no centro da imagem
480
- print("Imagem encontrada e clicada!")
562
+ pyautogui.click(local)
563
+ console.print("[ITENS] Imagem 'itens_nota.png' encontrada e clicada com sucesso!", style="bold green")
481
564
  break
482
565
  else:
483
- print("Imagem não encontrada, tentando novamente...")
566
+ console.print("[ITENS] Imagem 'itens_nota.png' não encontrada, tentando novamente...", style="yellow")
484
567
  time.sleep(1)
485
568
 
486
569
  await worker_sleep(3)
487
- # Clicar em itens da nota
570
+ console.print("[ITENS] Clicando em 'Itens da nota' por coordenada (fallback)...", style="cyan")
488
571
  pyautogui.click(791, 379)
489
572
  await worker_sleep(2)
573
+
574
+ console.print("[ITENS] Obtendo índice do último item via get_ultimo_item()...", style="bold cyan")
490
575
  index_item_atual = 0
491
576
  index_ultimo_item = await get_ultimo_item()
492
- console.print(f"Index ultimo item: {index_ultimo_item}")
577
+ console.print(f"[ITENS] Index último item retornado: {index_ultimo_item}", style="bold green")
493
578
 
494
579
  try:
580
+ console.print("[ITENS] Iniciando loop para tratar ICMS/IPI item a item...", style="bold cyan")
495
581
  while index_item_atual < index_ultimo_item:
582
+ console.print(f"[ITENS] Início do processamento do item índice {index_item_atual+1}/{index_ultimo_item}...", style="cyan")
496
583
  send_keys("^({HOME})")
497
584
  await worker_sleep(1)
498
585
 
@@ -507,32 +594,25 @@ async def opex_capex(task: RpaProcessoEntradaDTO) -> RpaRetornoProcessoDTO:
507
594
  send_keys("{ENTER}")
508
595
 
509
596
  await worker_sleep(2)
510
- app = Application().connect(title="Alteração de Item")
511
- main_window = app["Alteração de Item"]
597
+ app_alt = Application().connect(title="Alteração de Item")
598
+ win_alt = app_alt["Alteração de Item"]
599
+ win_alt.set_focus()
512
600
 
513
- main_window.set_focus()
514
-
515
- edit = main_window.child_window(
516
- class_name="TDBIEditCode", found_index=0
517
- )
601
+ _ = win_alt.child_window(class_name="TDBIEditCode", found_index=0)
518
602
  index_item_atual += 1
519
- console.print(f"Item aual no final da execução: {index_item_atual}")
603
+ console.print(f"[ITENS] Ítem atual no final da execução da tela: {index_item_atual}", style="cyan")
520
604
  await worker_sleep(1)
521
- # Listas
605
+
522
606
  lista_icms_090 = ["5101", "5102", "5103", "5104"]
523
607
  lista_icms_060 = ["5401", "5403", "5404", "5405", "6104", "6401", "6403", "6404", "6405"]
524
608
 
525
- # Conecta à janela
526
- app = Application().connect(class_name="TFrmAlteraItemNFE")
527
- main_window = app["TFrmAlteraItemNFE"]
528
- main_window.set_focus()
529
-
609
+ console.print("[ITENS] Conectando na janela TFrmAlteraItemNFE para ajuste ICMS/IPI...", style="cyan")
610
+ app_item = Application().connect(class_name="TFrmAlteraItemNFE")
611
+ win_item = app_item["TFrmAlteraItemNFE"]
612
+ win_item.set_focus()
530
613
 
531
- # Localiza o combobox
614
+ tipo_icms = win_item.child_window(class_name="TDBIComboBox", found_index=5)
532
615
 
533
- tipo_icms = main_window.child_window(class_name="TDBIComboBox", found_index=5)
534
-
535
- # Define o texto da opção desejada
536
616
  if cfop in lista_icms_090:
537
617
  opcao_desejada = "090 - ICMS NACIONAL OUTRAS"
538
618
  elif cfop in lista_icms_060:
@@ -540,186 +620,320 @@ async def opex_capex(task: RpaProcessoEntradaDTO) -> RpaRetornoProcessoDTO:
540
620
  else:
541
621
  opcao_desejada = None
542
622
 
543
- # Seleciona no combobox
623
+ console.print(f"[ITENS] CFOP item={cfop} | Opção ICMS desejada: {opcao_desejada}", style="cyan")
624
+
544
625
  if opcao_desejada:
545
626
  try:
546
627
  tipo_icms.select(opcao_desejada)
547
628
  send_keys("{ENTER}")
629
+ console.print(f"[ITENS] Tipo ICMS '{opcao_desejada}' selecionado com sucesso.", style="bold green")
548
630
  except Exception as e:
549
- print(f"Erro ao selecionar opção: {e}")
631
+ console.print(f"[ITENS] Erro ao selecionar opção ICMS no combobox: {e}", style="bold red")
632
+
633
+ combo_ipi = win_item.child_window(class_name="TDBIComboBox", found_index=4)
634
+ console.print("[ITENS] Selecionando IPI 0% no combobox de IPI...", style="cyan")
635
+ combo_ipi.select("IPI 0%")
636
+ console.print("[ITENS] IPI 0% selecionado com sucesso.", style="bold green")
550
637
 
551
- # Clicar em alterar
552
- main_window.child_window(class_name="TDBIBitBtn", found_index=3).click()
638
+ console.print("[ITENS] Clicando em 'Alterar' para confirmar mudanças do item...", style="cyan")
639
+ win_item.child_window(class_name="TDBIBitBtn", found_index=3).click()
640
+ else:
641
+ console.print("[ITENS] Nenhuma opção ICMS mapeada para este CFOP de item. Item será mantido como está.", style="yellow")
642
+
553
643
  await worker_sleep(5)
554
644
  except Exception as e:
555
- return {
556
- "sucesso": False,
557
- "retorno": f"Erro aotrabalhar nas alterações dos itens: {e}",
558
- }
559
-
645
+ console.print(f"[ITENS] Erro geral ao trabalhar nas alterações dos itens: {e}", style="bold red")
646
+ return RpaRetornoProcessoDTO(
647
+ sucesso=False,
648
+ retorno=f"Erro aotrabalhar nas alterações dos itens: {e}",
649
+ status=RpaHistoricoStatusEnum.Falha,
650
+ tags=[RpaTagDTO(descricao=RpaTagEnum.Tecnico)]
651
+ )
652
+
653
+ console.print("[ITENS] Finalizado o tratamento de todos os itens. Verificando pop-up de confirmação TMessageForm...", style="bold cyan")
654
+ try:
655
+ app_msg = Application().connect(class_name="TMessageForm")
656
+ win_msg = app_msg["TMessageForm"]
657
+ btn_ok = win_msg.child_window(title="&Yes", class_name="TButton")
658
+ btn_ok.click_input()
659
+ console.print("[ITENS] Pop-up TMessageForm confirmado com &Yes.", style="bold green")
660
+ except:
661
+ console.print("[ITENS] Nenhum pop-up TMessageForm de confirmação encontrado. Seguindo...", style="cyan")
662
+ pass
560
663
  await worker_sleep(10)
561
664
 
562
- console.print("Navegando pela Janela de Nota Fiscal de Entrada...\n")
563
- app = Application().connect(class_name="TFrmNotaFiscalEntrada")
564
- main_window = app["TFrmNotaFiscalEntrada"]
665
+ # ===================== PAGAMENTOS =====================
666
+ console.print("[PAGAMENTOS] Navegando pela janela de Nota Fiscal de Entrada (TFrmNotaFiscalEntrada)...", style="bold cyan")
667
+ app_nf = Application().connect(class_name="TFrmNotaFiscalEntrada")
668
+ nf_window = app_nf["TFrmNotaFiscalEntrada"]
565
669
 
566
- # Clicar em pagamentos
567
- imagem = r"C:\Users\automatehub\Documents\GitHub\worker-automate-hub\worker_automate_hub\assets\entrada_notas\pagamentos.png"
670
+ console.print("[PAGAMENTOS] Localizando aba 'Pagamentos' via imagem pagamentos.png...", style="bold cyan")
671
+ img_pag = fr"{BASE_PATH}\pagamentos.png"
568
672
 
569
- # Tenta localizar a imagem na tela
673
+ tentativas_pag = 0
570
674
  while True:
571
- local = pyautogui.locateCenterOnScreen(imagem, confidence=0.8) # 0.8 = 80% de precisão
675
+ tentativas_pag += 1
676
+ console.print(f"[PAGAMENTOS] Tentativa {tentativas_pag} de localizar 'pagamentos.png'...", style="cyan")
677
+ local = pyautogui.locateCenterOnScreen(img_pag, confidence=0.9)
572
678
  if local:
573
- pyautogui.click(local) # Clica no centro da imagem
574
- print("Imagem encontrada e clicada!")
679
+ pyautogui.click(local)
680
+ console.print("[PAGAMENTOS] Imagem 'pagamentos.png' encontrada e clicada com sucesso!", style="bold green")
575
681
  break
576
682
  else:
577
- print("Imagem não encontrada, tentando novamente...")
683
+ console.print("[PAGAMENTOS] Imagem 'pagamentos.png' não encontrada, tentando novamente...", style="yellow")
578
684
  time.sleep(1)
579
685
 
580
686
  await worker_sleep(3)
581
687
 
582
- panel_TPage = main_window.child_window(class_name="TPage", title="Formulario")
583
- panel_TTabSheet = panel_TPage.child_window(class_name="TPageControl")
584
-
585
- panel_TabPagamento = panel_TTabSheet.child_window(title="Pagamento")
586
-
587
- tipo_cobranca = panel_TTabSheet.child_window(
588
- class_name="TDBIComboBox", found_index=0
589
- )
590
- tipo_cobranca.click()
591
- # Lista de opções em ordem de prioridade
688
+ console.print("[PAGAMENTOS] Localizando combobox de Tipo de Cobrança na janela principal...", style="bold cyan")
592
689
  opcoes = [
593
690
  "BANCO DO BRASIL BOLETO FIDC",
594
691
  "BANCO DO BRASIL BOLETO",
595
- "BOLETO"
692
+ "BOLETO",
596
693
  ]
694
+ console.print(f"[PAGAMENTOS] Ordem de preferência tipo de cobrança: {opcoes}", style="cyan")
597
695
 
598
- # Vamos percorrer o combo com setas
599
- max_tentativas = 20 # evita loop infinito
600
- for _ in range(max_tentativas):
601
- texto_atual = tipo_cobranca.window_text().strip()
602
- if any(opcao.lower() == texto_atual.lower() for opcao in opcoes):
603
- send_keys("{ENTER}")
696
+ tipo_cobranca = None
697
+ try:
698
+ # primeiro chute: found_index=0 na janela principal
699
+ tipo_cobranca = nf_window.child_window(class_name="TDBIComboBox", found_index=0)
700
+ console.print("[PAGAMENTOS] Combobox de cobrança encontrado via found_index=0 na janela principal.", style="cyan")
701
+ except Exception as e:
702
+ console.print(f"[PAGAMENTOS] Falha ao localizar combobox de cobrança por found_index=0: {e}", style="yellow")
703
+ tipo_cobranca = None
704
+
705
+ if not tipo_cobranca:
706
+ console.print("[PAGAMENTOS] Tentando localizar combobox correto de cobrança analisando todos os TDBIComboBox...", style="cyan")
707
+ try:
708
+ candidatos = nf_window.descendants(class_name="TDBIComboBox")
709
+ except Exception as e:
710
+ console.print(f"[PAGAMENTOS] Erro ao obter descendants TDBIComboBox: {e}", style="bold red")
711
+ candidatos = []
712
+
713
+ for i, combo in enumerate(candidatos):
714
+ try:
715
+ itens_combo = [t.strip() for t in combo.item_texts() if str(t).strip()]
716
+ console.print(f"[PAGAMENTOS] Combo {i} itens encontrados: {itens_combo}", style="cyan")
717
+ texto_unico = " | ".join(itens_combo).lower()
718
+ if any(op.lower() in texto_unico for op in opcoes):
719
+ tipo_cobranca = combo
720
+ console.print(f"[PAGAMENTOS] Combo {i} escolhido como Tipo de Cobrança (contém alguma opção esperada).", style="bold green")
721
+ break
722
+ except Exception as e:
723
+ console.print(f"[PAGAMENTOS] Erro ao ler itens do combo {i}: {e}", style="yellow")
724
+
725
+ if not tipo_cobranca:
726
+ raise RuntimeError("Não foi possível localizar o combobox de Tipo de Cobrança na janela de Nota Fiscal de Entrada.")
727
+
728
+ # 1) Tenta select direto
729
+ selecionado = None
730
+ for alvo in opcoes:
731
+ try:
732
+ tipo_cobranca.select(alvo)
733
+ if tipo_cobranca.window_text().strip().lower() == alvo.lower():
734
+ selecionado = alvo
735
+ console.print(f"[PAGAMENTOS] Tipo de cobrança selecionado diretamente via .select(): {alvo}", style="bold green")
736
+ break
737
+ except Exception:
738
+ console.print(f"[PAGAMENTOS] Falha ao selecionar opção '{alvo}' via .select(). Tentando próximas opções...", style="yellow")
739
+ pass
740
+
741
+ # 2) Fallback: HOME + DOWN lendo texto
742
+ if not selecionado:
743
+ console.print("[PAGAMENTOS] Tentando selecionar tipo de cobrança navegando com setas (HOME + DOWN)...", style="bold cyan")
744
+ try:
745
+ tipo_cobranca.set_focus()
746
+ tipo_cobranca.click_input()
747
+ except Exception as e:
748
+ console.print(f"[PAGAMENTOS] Erro ao focar/clicar no combobox de cobrança: {e}", style="yellow")
749
+
750
+ send_keys('{HOME}')
751
+ vistos = set()
752
+ for _ in range(80):
753
+ atual = tipo_cobranca.window_text().strip()
754
+ atual_lower = atual.lower()
755
+ console.print(f"[PAGAMENTOS] Opção atualmente exibida no combo: '{atual}'", style="cyan")
756
+
757
+ match = False
758
+ for o in opcoes:
759
+ o_lower = o.lower()
760
+ if o_lower == atual_lower or o_lower in atual_lower:
761
+ match = True
762
+ selecionado = atual
763
+ break
764
+
765
+ if match:
766
+ send_keys('{ENTER}')
767
+ console.print(f"[PAGAMENTOS] Tipo de cobrança selecionado via navegação por setas: '{selecionado}'", style="bold green")
768
+ break
769
+
770
+ if atual_lower in vistos:
771
+ console.print("[PAGAMENTOS] Deu a volta na lista de tipos de cobrança. Abortando navegação.", style="yellow")
772
+ break
773
+
774
+ vistos.add(atual_lower)
775
+ send_keys('{DOWN}')
776
+
777
+ erro_tipo = tipo_cobranca.window_text().strip()
778
+ erro_tipo_lower = erro_tipo.lower()
779
+
780
+ valido = False
781
+ for o in opcoes:
782
+ o_lower = o.lower()
783
+ if o_lower == erro_tipo_lower or o_lower in erro_tipo_lower:
784
+ valido = True
604
785
  break
605
- send_keys("{DOWN}")
606
-
607
- await worker_sleep(3)
608
-
609
- dt_vencimento_nota = nota.get("dataVencimento") # vem como '2025-09-26'
610
- data_atual = datetime.now().date()
611
786
 
612
- # Converte para date (formato yyyy-mm-dd → ISO)
613
- data_vencimento = datetime.strptime(dt_vencimento_nota, "%Y-%m-%d").date()
787
+ if not selecionado or not valido:
788
+ console.print(
789
+ f"[PAGAMENTOS] Não foi possível confirmar uma opção válida de cobrança. Ficou: '{erro_tipo}'",
790
+ style="bold red"
791
+ )
792
+ raise RuntimeError(f"Não consegui selecionar uma opção válida. Ficou: '{erro_tipo}'")
614
793
 
615
- # Se o vencimento for hoje ou já passou, joga para próximo dia útil
616
- if data_vencimento <= data_atual:
617
- data_vencimento = data_atual + timedelta(days=1)
794
+ console.print(f"[PAGAMENTOS] Tipo de cobrança final selecionado: {erro_tipo}", style="bold green")
618
795
 
619
- # Ajusta para cair em dias úteis
620
- while data_vencimento.weekday() >= 5: # 5 = sábado, 6 = domingo
796
+ # ========= DATA DE VENCIMENTO =========
797
+ console.print("[PAGAMENTOS] Calculando e ajustando data de vencimento da parcela...", style="bold cyan")
798
+ dt_vencimento_nota = nota.get("dataVencimento")
799
+ data_atual_date = datetime.now().date()
800
+ console.print(f"[PAGAMENTOS] Data vencimento original (configEntrada): {dt_vencimento_nota}", style="cyan")
801
+
802
+ data_vencimento = datetime.strptime(dt_vencimento_nota, "%Y-%m-%d").date()
803
+
804
+ if data_vencimento <= data_atual_date:
805
+ console.print("[PAGAMENTOS] Data de vencimento original é hoje ou já passou. Ajustando para próximo dia útil...", style="yellow")
806
+ data_vencimento = data_atual_date + timedelta(days=1)
807
+ while data_vencimento.weekday() >= 5:
621
808
  data_vencimento += timedelta(days=1)
622
809
 
623
- # Converter para string (formato brasileiro dd/mm/yyyy)
624
810
  data_vencimento_str = data_vencimento.strftime("%d/%m/%Y")
625
- print("Novo vencimento:", data_vencimento_str)
626
-
627
- # Inserir no campo
628
- data_venc = panel_TTabSheet.child_window(
629
- class_name="TDBIEditDate", found_index=0
630
- )
811
+ console.print(f"[PAGAMENTOS] Nova data de vencimento calculada: {data_vencimento_str}", style="bold green")
631
812
 
813
+ console.print("[PAGAMENTOS] Inserindo data de vencimento no campo TDBIEditDate (found_index=0)...", style="cyan")
814
+ data_venc = nf_window.child_window(class_name="TDBIEditDate", found_index=0)
632
815
  data_venc.set_edit_text(data_vencimento_str)
633
816
 
634
- console.print(f"Incluindo registro...\n")
817
+ console.print("[PAGAMENTOS] Incluindo registro de parcela (delete + inclui novamente)...", style="bold cyan")
818
+
635
819
  try:
636
- ASSETS_PATH = "assets"
637
- inserir_registro = pyautogui.locateOnScreen(
638
- r"C:\Users\automatehub\Documents\GitHub\worker-automate-hub\assets\entrada_notas\IncluirRegistro.png", confidence=0.8
639
- )
820
+ console.print("[PAGAMENTOS] Excluindo parcela existente (se houver)...", style="cyan")
821
+ nf_window.child_window(class_name="TDBIBitBtn", found_index=0).click_input()
822
+ await worker_sleep(3)
823
+ app_del = Application().connect(class_name="TMessageForm")
824
+ main_del = app_del["TMessageForm"]
825
+ btn_ok = main_del.child_window(title="&Yes", class_name="TButton")
826
+ btn_ok.click_input()
827
+ console.print("[PAGAMENTOS] Parcela antiga excluída com sucesso.", style="bold green")
828
+ await worker_sleep(3)
829
+
830
+ valor = nf_window.child_window(class_name="TDBIEditNumber", found_index=7)
831
+ valor_encontrado = valor.window_text()
832
+ console.print(f"[PAGAMENTOS] Valor da parcela lido (antes de tratar ponto): {valor_encontrado}", style="cyan")
833
+ valor_encontrado = valor_encontrado.replace(".","")
834
+ console.print(f"[PAGAMENTOS] Valor da parcela após remover '.': {valor_encontrado}", style="cyan")
835
+
836
+ await worker_sleep(3)
837
+
838
+ inserir_valor = nf_window.child_window(class_name="TDBIEditNumber", found_index=3)
839
+ console.print("[PAGAMENTOS] Inserindo valor tratado no campo index 3...", style="cyan")
840
+ inserir_valor.set_focus()
841
+ send_keys("^a{DEL}")
842
+ send_keys(valor_encontrado)
843
+
844
+ console.print("[PAGAMENTOS] Incluindo nova parcela...", style="cyan")
845
+ nf_window.child_window(class_name="TDBIBitBtn", found_index=1).click_input()
846
+ console.print("[PAGAMENTOS] Parcela incluída com sucesso.", style="bold green")
847
+ except Exception as e:
848
+ console.print(f"[PAGAMENTOS] Erro ao excluir/incluir parcela de pagamento: {e}. Prosseguindo com fallback de inclusão de registro.", style="yellow")
849
+
850
+ console.print("[PAGAMENTOS] Tentando incluir registro via imagem IncluirRegistro.png...", style="bold cyan")
851
+ try:
852
+ inserir_registro = pyautogui.locateOnScreen(fr"{BASE_PATH}\IncluirRegistro.png", confidence=0.8)
640
853
  pyautogui.click(inserir_registro)
854
+ console.print("[PAGAMENTOS] Botão de 'Incluir Registro' clicado via imagem com sucesso.", style="bold green")
641
855
  except Exception as e:
642
856
  console.print(
643
- f"Não foi possivel incluir o registro utilizando reconhecimento de imagem, Error: {e}...\n tentando inserir via posição...\n"
857
+ f"[PAGAMENTOS] Não foi possivel incluir o registro utilizando reconhecimento de imagem, Error: {e}...\n tentando inserir via posição...",
858
+ style="yellow"
644
859
  )
645
860
  await incluir_registro()
861
+ console.print("[PAGAMENTOS] Fallback incluir_registro() executado.", style="cyan")
646
862
 
647
863
  await worker_sleep(10)
648
-
649
- console.print(
650
- "Verificando a existencia de POP-UP de Itens que Ultrapassam a Variação Máxima de Custo ...\n"
651
- )
652
- itens_variacao_maxima = await is_window_open_by_class(
653
- "TFrmTelaSelecao", "TFrmTelaSelecao"
654
- )
655
- if itens_variacao_maxima["IsOpened"] == True:
656
- app = Application().connect(class_name="TFrmTelaSelecao")
657
- main_window = app["TFrmTelaSelecao"]
658
- send_keys("%o")
659
864
 
660
- await worker_sleep(2)
661
- console.print(
662
- "Verificando a existencia de Warning informando que a Soma dos pagamentos não bate com o valor da nota. ...\n"
663
- )
664
- app = Application().connect(class_name="TFrmNotaFiscalEntrada")
665
- main_window = app["TFrmNotaFiscalEntrada"]
865
+ # ================= RATEIO / FINALIZAÇÃO =================
866
+ console.print("[RATEIO] Tratando pop-ups e aguardando tela de Rateio da Despesa...", style="bold cyan")
666
867
 
667
868
  try:
668
- warning_pop_up_pagamentos = main_window.child_window(
669
- class_name="TMessageForm", title="Warning"
670
- )
671
- except:
672
- warning_pop_up_pagamentos = None
673
-
674
- if warning_pop_up_pagamentos.exists():
675
- console.print(
676
- "Erro: Warning informando que a Soma dos pagamentos não bate com o valor da nota. ...\n"
677
- )
678
- return RpaRetornoProcessoDTO(
679
- sucesso=False,
680
- retorno=f"A soma dos pagamentos não bate com o valor da nota.",
681
- status=RpaHistoricoStatusEnum.Falha,
682
- tags=[RpaTagDTO(descricao=RpaTagEnum.Negocio)]
683
- )
684
- else:
685
- console.print(
686
- "Warning informando que a Soma dos pagamentos não bate com o valor da nota não existe ...\n"
687
- )
688
-
689
- max_attempts = 7
690
- i = 0
691
- aguarde_rateio_despesa = True
692
-
693
- while i < max_attempts:
694
- await worker_sleep(3)
695
-
696
- from pywinauto import Desktop
869
+ console.print("[RATEIO] Verificando POP-UP 'Itens que Ultrapassam a Variação Máxima de Custo'...", style="cyan")
870
+ itens_variacao_maxima = await is_window_open_by_class("TFrmTelaSelecao", "TFrmTelaSelecao")
871
+ console.print(f"[RATEIO] Retorno is_window_open_by_class para TFrmTelaSelecao: {itens_variacao_maxima}", style="cyan")
872
+
873
+ if itens_variacao_maxima.get("IsOpened"):
874
+ console.print("[RATEIO] Pop-up encontrado. Confirmando (ALT+O)...", style="yellow")
875
+ app_sel = Application().connect(class_name="TFrmTelaSelecao")
876
+ win_sel = app_sel["TFrmTelaSelecao"]
877
+ win_sel.set_focus()
878
+ send_keys("%o")
879
+ console.print("[RATEIO] POP-UP tratado com sucesso.", style="bold green")
880
+ except Exception as error:
881
+ console.print(f"[RATEIO] Falha ao verificar POP-UP de variação máxima: {error}", style="bold red")
697
882
 
698
- for window in Desktop(backend="uia").windows():
699
- if "Rateio" in window.window_text():
700
- aguarde_rateio_despesa = False
701
- console.print(
702
- "A janela 'Rateio da Despesas' foi encontrada. Continuando para andamento do processo...\n"
703
- )
704
- break
883
+ await worker_sleep(2)
705
884
 
706
- if not aguarde_rateio_despesa:
707
- break
885
+ console.print("[RATEIO] Verificando se a tela de 'Rateio da Despesa' já está aberta...", style="bold cyan")
886
+ rateio_aberto = False
887
+ try:
888
+ rateio_win = Desktop(backend="uia").window(title_re=".*Rateio.*")
889
+ rateio_aberto = rateio_win.exists(timeout=1)
890
+ console.print(f"[RATEIO] Tela de rateio aberta? {rateio_aberto}", style="cyan")
891
+ except Exception as e:
892
+ console.print(f"[RATEIO] Erro ao verificar tela de rateio: {e}", style="yellow")
893
+ rateio_aberto = False
708
894
 
709
- i += 1
895
+ if not rateio_aberto:
896
+ console.print("[RATEIO] Tela de rateio não aberta. Verificando Warning de soma pagamentos x valor da nota...", style="cyan")
897
+ try:
898
+ warning_app = Application().connect(title="Warning")
899
+ warning_pop_up_pagamentos = warning_app["Warning"]
900
+ existe_warning_pagamentos = warning_pop_up_pagamentos.exists(timeout=1)
901
+ except Exception:
902
+ existe_warning_pagamentos = False
903
+
904
+ if existe_warning_pagamentos:
905
+ console.print("[RATEIO] Warning encontrado: soma dos pagamentos não bate com o valor da nota.", style="bold red")
906
+ return RpaRetornoProcessoDTO(
907
+ sucesso=False,
908
+ retorno="A soma dos pagamentos não bate com o valor da nota.",
909
+ status=RpaHistoricoStatusEnum.Falha,
910
+ tags=[RpaTagDTO(descricao=RpaTagEnum.Negocio)]
911
+ )
912
+ else:
913
+ console.print("[RATEIO] Warning de soma dos pagamentos não encontrado. Seguindo com o processo...", style="bold green")
914
+ else:
915
+ console.print("[RATEIO] Tela de Rateio da Despesa já está aberta. Ignorando validação de Warning de pagamentos.", style="cyan")
710
916
 
711
- if aguarde_rateio_despesa:
917
+ console.print("[RATEIO] Aguardando a tela 'Rateio da Despesa'...", style="bold cyan")
918
+ try:
919
+ rateio_win = Desktop(backend="uia").window(title_re=".*Rateio.*")
920
+ rateio_win.wait("exists enabled visible ready", timeout=30)
921
+ console.print("[RATEIO] Tela 'Rateio da Despesa' encontrada. Prosseguindo com o rateio...", style="bold green")
922
+ except Exception as e:
923
+ console.print(f"[RATEIO] Erro ao aguardar tela de Rateio: {e}", style="bold red")
712
924
  return RpaRetornoProcessoDTO(
713
925
  sucesso=False,
714
- retorno=f"Número máximo de tentativas atingido. A tela para Rateio da Despesa não foi encontrada.",
926
+ retorno="Número máximo de tentativas atingido. A tela para Rateio da Despesa não foi encontrada.",
715
927
  status=RpaHistoricoStatusEnum.Falha,
716
928
  tags=[RpaTagDTO(descricao=RpaTagEnum.Tecnico)]
717
929
  )
718
930
 
931
+ console.print("[RATEIO] Chamando função rateio_despesa()...", style="bold cyan")
719
932
  despesa_rateio_work = await rateio_despesa(empresaCodigo)
720
- if despesa_rateio_work.sucesso == True:
933
+ if despesa_rateio_work.sucesso:
721
934
  console.log(despesa_rateio_work.retorno, style="bold green")
722
935
  else:
936
+ console.print("[RATEIO] Falha ao executar rateio_despesa.", style="bold red")
723
937
  return RpaRetornoProcessoDTO(
724
938
  sucesso=False,
725
939
  retorno=despesa_rateio_work.retorno,
@@ -727,86 +941,80 @@ async def opex_capex(task: RpaProcessoEntradaDTO) -> RpaRetornoProcessoDTO:
727
941
  tags=despesa_rateio_work.tags
728
942
  )
729
943
 
730
- # Verifica se a info 'Nota fiscal incluida' está na tela
944
+ console.print("[FINALIZAÇÃO] Aguardando warnings finais e validação da nota lançada...", style="bold cyan")
731
945
  await worker_sleep(15)
732
946
  warning_pop_up = await is_window_open("Warning")
733
- if warning_pop_up["IsOpened"] == True:
734
- app = Application().connect(title="Warning")
735
- main_window = app["Warning"]
736
- main_window.set_focus()
737
-
738
- console.print(f"Obtendo texto do Warning...\n")
739
- console.print(f"Tirando print da janela do warning para realização do OCR...\n")
947
+ if warning_pop_up["IsOpened"]:
948
+ console.print("[FINALIZAÇÃO] Pop-up 'Warning' encontrado no fim do fluxo. Capturando mensagem com OCR...", style="yellow")
949
+ app_w = Application().connect(title="Warning")
950
+ win_w = app_w["Warning"]
951
+ win_w.set_focus()
740
952
 
741
- window_rect = main_window.rectangle()
953
+ window_rect = win_w.rectangle()
742
954
  screenshot = pyautogui.screenshot(
743
- region=(
744
- window_rect.left,
745
- window_rect.top,
746
- window_rect.width(),
747
- window_rect.height(),
748
- )
955
+ region=(window_rect.left, window_rect.top, window_rect.width(), window_rect.height())
749
956
  )
750
957
  username = getpass.getuser()
751
- path_to_png = f"C:\\Users\\{username}\\Downloads\\warning_popup_{nota.get("nfe")}.png"
958
+ path_to_png = f"C:\\Users\\{username}\\Downloads\\warning_popup_{nota.get('nfe')}.png"
752
959
  screenshot.save(path_to_png)
753
- console.print(f"Print salvo em {path_to_png}...\n")
960
+ console.print(f"[FINALIZAÇÃO] Print do Warning salvo em {path_to_png}", style="cyan")
754
961
 
755
- console.print(
756
- f"Preparando a imagem para maior resolução e assertividade no OCR...\n"
757
- )
758
962
  image = Image.open(path_to_png)
759
963
  image = image.convert("L")
760
964
  enhancer = ImageEnhance.Contrast(image)
761
965
  image = enhancer.enhance(2.0)
762
966
  image.save(path_to_png)
763
- console.print(f"Imagem preparada com sucesso...\n")
764
- console.print(f"Realizando OCR...\n")
967
+ console.print("[FINALIZAÇÃO] Imagem preparada. Iniciando OCR...", style="cyan")
765
968
  captured_text = pytesseract.image_to_string(Image.open(path_to_png))
766
- console.print(
767
- f"Texto Full capturado {captured_text}...\n"
768
- )
969
+ console.print(f"[FINALIZAÇÃO] Texto capturado do Warning: {captured_text}", style="bold green")
769
970
  os.remove(path_to_png)
971
+ console.print("[FINALIZAÇÃO] Arquivo de imagem do Warning removido.", style="cyan")
972
+
770
973
  if 'movimento não permitido' in captured_text.lower():
974
+ console.print("[FINALIZAÇÃO] Warning mapeado: movimento não permitido (livro fechado).", style="bold red")
771
975
  return RpaRetornoProcessoDTO(
772
- sucesso=False,
773
- retorno=f"Filial: {empresaCodigo} está com o livro fechado ou encerrado, verificar com o setor fiscal",
774
- status=RpaHistoricoStatusEnum.Falha,
775
- tags=[RpaTagDTO(descricao=RpaTagEnum.Negocio)]
976
+ sucesso=False,
977
+ retorno=f"Filial: {empresaCodigo} está com o livro fechado ou encerrado, verificar com o setor fiscal",
978
+ status=RpaHistoricoStatusEnum.Falha,
979
+ tags=[RpaTagDTO(descricao=RpaTagEnum.Negocio)]
776
980
  )
777
981
  else:
982
+ console.print("[FINALIZAÇÃO] Warning não mapeado. Retornando como erro técnico com mensagem completa do OCR.", style="bold red")
778
983
  return RpaRetornoProcessoDTO(
779
- sucesso=False,
780
- retorno=f"Warning não mapeado para seguimento do robo, mensagem: {captured_text}",
781
- status=RpaHistoricoStatusEnum.Falha,
782
- tags=[RpaTagDTO(descricao=RpaTagEnum.Tecnico)]
984
+ sucesso=False,
985
+ retorno=f"Warning não mapeado para seguimento do robo, mensagem: {captured_text}",
986
+ status=RpaHistoricoStatusEnum.Falha,
987
+ tags=[RpaTagDTO(descricao=RpaTagEnum.Tecnico)]
783
988
  )
784
989
 
785
990
  await worker_sleep(3)
786
- # Verifica se a nota foi lançada
991
+
992
+ console.print("[FINALIZAÇÃO] Verificando se a nota foi lançada via check_nota_importada...", style="bold cyan")
787
993
  nf_imported = await check_nota_importada(dados_nf[0].get("chaveNfe"))
788
- if nf_imported.sucesso == True:
994
+ console.print(f"[FINALIZAÇÃO] Retorno check_nota_importada: sucesso={nf_imported.sucesso} | retorno={nf_imported.retorno}", style="cyan")
995
+ if nf_imported.sucesso:
789
996
  await worker_sleep(3)
790
- console.print("\nVerifica se a nota ja foi lançada...")
791
- nf_chave_acesso = int(dados_nf[0].get("chaveNfe"))
792
- status_nf_emsys = await get_status_nf_emsys(nf_chave_acesso)
997
+ console.print("[FINALIZAÇÃO] Validando status da NF no EMSys via get_status_nf_emsys...", style="bold cyan")
998
+ nf_chave_int = int(dados_nf[0].get("chaveNfe"))
999
+ status_nf_emsys = await get_status_nf_emsys(nf_chave_int)
1000
+ console.print(f"[FINALIZAÇÃO] Status NF EMSys pós-lançamento: {status_nf_emsys}", style="cyan")
793
1001
  if status_nf_emsys.get("status") == "Lançada":
794
- console.print("\nNota lançada com sucesso, processo finalizado...", style="bold green")
1002
+ console.print("\n[FINALIZAÇÃO] Nota lançada com sucesso, processo finalizado...", style="bold green")
795
1003
  return RpaRetornoProcessoDTO(
796
1004
  sucesso=True,
797
1005
  retorno="Nota Lançada com sucesso!",
798
1006
  status=RpaHistoricoStatusEnum.Sucesso,
799
1007
  )
800
1008
  else:
801
- console.print("Erro ao lançar nota", style="bold red")
1009
+ console.print("[FINALIZAÇÃO] Pop-up nota incluída encontrado, porém status retornou diferente de 'Lançada'.", style="bold red")
802
1010
  return RpaRetornoProcessoDTO(
803
1011
  sucesso=False,
804
- retorno=f"Pop-up nota incluida encontrada, porém nota encontrada como 'já lançada' trazendo as seguintes informações: {nf_imported.retorno} - {error_work}",
1012
+ retorno=f"Pop-up nota incluida encontrada, porém nota encontrada como 'já lançada' trazendo as seguintes informações: {nf_imported.retorno}",
805
1013
  status=RpaHistoricoStatusEnum.Falha,
806
1014
  tags=[RpaTagDTO(descricao=RpaTagEnum.Negocio)]
807
1015
  )
808
1016
  else:
809
- console.print("Erro ao lançar nota", style="bold red")
1017
+ console.print("[FINALIZAÇÃO] check_nota_importada retornou falha. Nota não confirmada como lançada.", style="bold red")
810
1018
  return RpaRetornoProcessoDTO(
811
1019
  sucesso=False,
812
1020
  retorno=f"Erro ao lançar nota, erro: {nf_imported.retorno}",
@@ -815,7 +1023,7 @@ async def opex_capex(task: RpaProcessoEntradaDTO) -> RpaRetornoProcessoDTO:
815
1023
  )
816
1024
 
817
1025
  except Exception as ex:
818
- observacao = f"Erro Processo Entrada de Notas: {str(ex)}"
1026
+ observacao = f"[ERRO GERAL] Erro Processo Entrada de Notas: {str(ex)}"
819
1027
  logger.error(observacao)
820
1028
  console.print(observacao, style="bold red")
821
1029
  return RpaRetornoProcessoDTO(
@@ -826,7 +1034,13 @@ async def opex_capex(task: RpaProcessoEntradaDTO) -> RpaRetornoProcessoDTO:
826
1034
  )
827
1035
 
828
1036
  finally:
829
- # Deleta o xml
830
- await delete_xml(numero_nota)
831
-
832
-
1037
+ console.print("[FINALLY] Iniciando limpeza de XML (delete_xml)...", style="bold cyan")
1038
+ try:
1039
+ if numero_nota:
1040
+ await delete_xml(numero_nota)
1041
+ console.print(f"[FINALLY] XML da nota {numero_nota} deletado com sucesso.", style="bold green")
1042
+ else:
1043
+ console.print("[FINALLY] numero_nota é None, não foi possível chamar delete_xml com parâmetro válido.", style="yellow")
1044
+ except Exception as e:
1045
+ console.print(f"[FINALLY] Falha ao deletar XML da nota {numero_nota}: {e}", style="bold red")
1046
+ console.print("\n================ FIM PROCESSO opex_capex ================\n", style="bold blue")