worker-automate-hub 0.5.820__py3-none-any.whl → 0.5.921__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 (24) hide show
  1. worker_automate_hub/api/client.py +121 -10
  2. worker_automate_hub/api/rpa_historico_service.py +1 -0
  3. worker_automate_hub/tasks/jobs/abertura_livros_fiscais.py +11 -14
  4. worker_automate_hub/tasks/jobs/descartes.py +8 -8
  5. worker_automate_hub/tasks/jobs/devolucao_produtos.py +1386 -0
  6. worker_automate_hub/tasks/jobs/extracao_dados_nielsen.py +504 -0
  7. worker_automate_hub/tasks/jobs/extracao_saldo_estoque_fiscal.py +90 -11
  8. worker_automate_hub/tasks/jobs/fidc_gerar_nosso_numero.py +2 -2
  9. worker_automate_hub/tasks/jobs/fidc_remessa_cobranca_cnab240.py +24 -15
  10. worker_automate_hub/tasks/jobs/importacao_extratos.py +538 -0
  11. worker_automate_hub/tasks/jobs/importacao_extratos_748.py +800 -0
  12. worker_automate_hub/tasks/jobs/inclusao_pedidos_ipiranga.py +223 -0
  13. worker_automate_hub/tasks/jobs/inclusao_pedidos_raizen.py +187 -0
  14. worker_automate_hub/tasks/jobs/inclusao_pedidos_vibra.py +345 -0
  15. worker_automate_hub/tasks/jobs/lista_clientes_sap.py +631 -0
  16. worker_automate_hub/tasks/jobs/lista_devolucoes_sap.py +626 -0
  17. worker_automate_hub/tasks/jobs/notas_faturamento_sap.py +438 -157
  18. worker_automate_hub/tasks/jobs/opex_capex.py +523 -384
  19. worker_automate_hub/tasks/task_definitions.py +38 -2
  20. worker_automate_hub/utils/util.py +20 -10
  21. {worker_automate_hub-0.5.820.dist-info → worker_automate_hub-0.5.921.dist-info}/METADATA +2 -1
  22. {worker_automate_hub-0.5.820.dist-info → worker_automate_hub-0.5.921.dist-info}/RECORD +24 -15
  23. {worker_automate_hub-0.5.820.dist-info → worker_automate_hub-0.5.921.dist-info}/WHEEL +0 -0
  24. {worker_automate_hub-0.5.820.dist-info → worker_automate_hub-0.5.921.dist-info}/entry_points.txt +0 -0
@@ -17,7 +17,9 @@ from pywinauto_recorder.player import set_combobox
17
17
  from rich.console import Console
18
18
  import sys
19
19
  import asyncio
20
- # sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..","..","..")))
20
+ from pywinauto import Desktop
21
+
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 (
23
25
  get_config_by_name,
@@ -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,31 +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 = "assets\\entrada_notas\\itens_nota.png"
474
- # imagem = r"C:\Users\automatehub\Documents\GitHub\worker-automate-hub\assets\entrada_notas\itens_nota.png"
475
-
476
- # 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
477
557
  while True:
478
- 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)
479
561
  if local:
480
- pyautogui.click(local) # Clica no centro da imagem
481
- 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")
482
564
  break
483
565
  else:
484
- print("Imagem não encontrada, tentando novamente...")
566
+ console.print("[ITENS] Imagem 'itens_nota.png' não encontrada, tentando novamente...", style="yellow")
485
567
  time.sleep(1)
486
568
 
487
569
  await worker_sleep(3)
488
- # Clicar em itens da nota
570
+ console.print("[ITENS] Clicando em 'Itens da nota' por coordenada (fallback)...", style="cyan")
489
571
  pyautogui.click(791, 379)
490
572
  await worker_sleep(2)
573
+
574
+ console.print("[ITENS] Obtendo índice do último item via get_ultimo_item()...", style="bold cyan")
491
575
  index_item_atual = 0
492
576
  index_ultimo_item = await get_ultimo_item()
493
- console.print(f"Index ultimo item: {index_ultimo_item}")
577
+ console.print(f"[ITENS] Index último item retornado: {index_ultimo_item}", style="bold green")
494
578
 
495
579
  try:
580
+ console.print("[ITENS] Iniciando loop para tratar ICMS/IPI item a item...", style="bold cyan")
496
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")
497
583
  send_keys("^({HOME})")
498
584
  await worker_sleep(1)
499
585
 
@@ -508,32 +594,25 @@ async def opex_capex(task: RpaProcessoEntradaDTO) -> RpaRetornoProcessoDTO:
508
594
  send_keys("{ENTER}")
509
595
 
510
596
  await worker_sleep(2)
511
- app = Application().connect(title="Alteração de Item")
512
- main_window = app["Alteração de Item"]
513
-
514
- main_window.set_focus()
597
+ app_alt = Application().connect(title="Alteração de Item")
598
+ win_alt = app_alt["Alteração de Item"]
599
+ win_alt.set_focus()
515
600
 
516
- edit = main_window.child_window(
517
- class_name="TDBIEditCode", found_index=0
518
- )
601
+ _ = win_alt.child_window(class_name="TDBIEditCode", found_index=0)
519
602
  index_item_atual += 1
520
- 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")
521
604
  await worker_sleep(1)
522
- # Listas
605
+
523
606
  lista_icms_090 = ["5101", "5102", "5103", "5104"]
524
607
  lista_icms_060 = ["5401", "5403", "5404", "5405", "6104", "6401", "6403", "6404", "6405"]
525
608
 
526
- # Conecta à janela
527
- app = Application().connect(class_name="TFrmAlteraItemNFE")
528
- main_window = app["TFrmAlteraItemNFE"]
529
- main_window.set_focus()
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
 
614
+ tipo_icms = win_item.child_window(class_name="TDBIComboBox", found_index=5)
531
615
 
532
- # Localiza o combobox
533
-
534
- tipo_icms = main_window.child_window(class_name="TDBIComboBox", found_index=5)
535
-
536
- # Define o texto da opção desejada
537
616
  if cfop in lista_icms_090:
538
617
  opcao_desejada = "090 - ICMS NACIONAL OUTRAS"
539
618
  elif cfop in lista_icms_060:
@@ -541,262 +620,320 @@ async def opex_capex(task: RpaProcessoEntradaDTO) -> RpaRetornoProcessoDTO:
541
620
  else:
542
621
  opcao_desejada = None
543
622
 
544
- # Seleciona no combobox
623
+ console.print(f"[ITENS] CFOP item={cfop} | Opção ICMS desejada: {opcao_desejada}", style="cyan")
624
+
545
625
  if opcao_desejada:
546
626
  try:
547
627
  tipo_icms.select(opcao_desejada)
548
628
  send_keys("{ENTER}")
629
+ console.print(f"[ITENS] Tipo ICMS '{opcao_desejada}' selecionado com sucesso.", style="bold green")
549
630
  except Exception as e:
550
- print(f"Erro ao selecionar opção: {e}")
551
- # Localize o combobox pelo class_name
552
- combo = main_window.child_window(class_name="TDBIComboBox", found_index=4)
553
-
554
- # Seleciona diretamente o texto
555
- combo.select("IPI 0%")
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")
556
637
 
557
- # Clicar em alterar
558
- 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
+
559
643
  await worker_sleep(5)
560
644
  except Exception as e:
561
- return {
562
- "sucesso": False,
563
- "retorno": f"Erro aotrabalhar nas alterações dos itens: {e}",
564
- }
565
-
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
566
663
  await worker_sleep(10)
567
664
 
568
- console.print("Navegando pela Janela de Nota Fiscal de Entrada...\n")
569
- app = Application().connect(class_name="TFrmNotaFiscalEntrada")
570
- 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"]
571
669
 
572
- # Clicar em pagamentos
573
- # imagem = r"C:\Users\automatehub\Documents\GitHub\worker-automate-hub\worker_automate_hub\assets\entrada_notas\pagamentos.png"
574
- imagem = "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"
575
672
 
576
- # Tenta localizar a imagem na tela
673
+ tentativas_pag = 0
577
674
  while True:
578
- local = pyautogui.locateCenterOnScreen(imagem, confidence=0.9) # 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)
579
678
  if local:
580
- pyautogui.click(local) # Clica no centro da imagem
581
- print("Imagem encontrada e clicada!")
679
+ pyautogui.click(local)
680
+ console.print("[PAGAMENTOS] Imagem 'pagamentos.png' encontrada e clicada com sucesso!", style="bold green")
582
681
  break
583
682
  else:
584
- print("Imagem não encontrada, tentando novamente...")
683
+ console.print("[PAGAMENTOS] Imagem 'pagamentos.png' não encontrada, tentando novamente...", style="yellow")
585
684
  time.sleep(1)
586
685
 
587
686
  await worker_sleep(3)
588
687
 
589
- panel_TPage = main_window.child_window(class_name="TPage", title="Formulario")
590
- panel_TTabSheet = panel_TPage.child_window(class_name="TPageControl")
591
-
592
- panel_TabPagamento = panel_TTabSheet.child_window(title="Pagamento")
593
-
594
- # Combo alvo (ajuste found_index se precisar)
595
- tipo_cobranca = panel_TTabSheet.child_window(class_name="TDBIComboBox", found_index=0)
596
-
597
- # Ordem de preferência
688
+ console.print("[PAGAMENTOS] Localizando combobox de Tipo de Cobrança na janela principal...", style="bold cyan")
598
689
  opcoes = [
599
690
  "BANCO DO BRASIL BOLETO FIDC",
600
691
  "BANCO DO BRASIL BOLETO",
601
692
  "BOLETO",
602
693
  ]
694
+ console.print(f"[PAGAMENTOS] Ordem de preferência tipo de cobrança: {opcoes}", style="cyan")
695
+
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")
603
724
 
604
- # 1) Tenta .select() direto (não digita nada)
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
605
729
  selecionado = None
606
730
  for alvo in opcoes:
607
731
  try:
608
732
  tipo_cobranca.select(alvo)
609
733
  if tipo_cobranca.window_text().strip().lower() == alvo.lower():
610
734
  selecionado = alvo
735
+ console.print(f"[PAGAMENTOS] Tipo de cobrança selecionado diretamente via .select(): {alvo}", style="bold green")
611
736
  break
612
737
  except Exception:
738
+ console.print(f"[PAGAMENTOS] Falha ao selecionar opção '{alvo}' via .select(). Tentando próximas opções...", style="yellow")
613
739
  pass
614
740
 
615
- # 2) Abre a LISTA e seleciona o item exato (sem digitar)
741
+ # 2) Fallback: HOME + DOWN lendo texto
616
742
  if not selecionado:
617
- tipo_cobranca.set_focus()
618
- tipo_cobranca.click_input()
619
- send_keys('%{DOWN}') # ALT+DOWN para abrir o dropdown
620
- # tenta achar a janela da lista (Delphi/Win32)
621
- lista = None
622
- app = tipo_cobranca.app
623
- for crit in (dict(title="||List"), dict(class_name="ComboLBox"), dict(class_name_re=".*(List|Combo).*")):
624
- try:
625
- cand = app.window(**crit)
626
- if cand.exists(timeout=0.5):
627
- lista = cand
628
- break
629
- except Exception:
630
- pass
631
-
632
- if lista:
633
- # tenta selecionar por índice (texto exato)
634
- try:
635
- itens = [t.strip() for t in lista.texts() if str(t).strip()]
636
- except Exception:
637
- itens = []
638
-
639
- idx_alvo = -1
640
- alvo_escolhido = None
641
- for alvo in opcoes:
642
- for i, t in enumerate(itens):
643
- if t.lower() == alvo.lower():
644
- idx_alvo = i
645
- alvo_escolhido = alvo
646
- break
647
- if idx_alvo >= 0:
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
648
763
  break
649
764
 
650
- if idx_alvo >= 0:
651
- try:
652
- lista.select(idx_alvo)
653
- except Exception:
654
- # fallback por teclas sem digitar texto do item
655
- send_keys('{HOME}')
656
- for _ in range(idx_alvo):
657
- send_keys('{DOWN}')
765
+ if match:
658
766
  send_keys('{ENTER}')
659
- try:
660
- wait_until(2, 0.2, lambda: tipo_cobranca.window_text().strip() != "")
661
- except PywTimeout:
662
- pass
663
- if tipo_cobranca.window_text().strip().lower() == alvo_escolhido.lower():
664
- selecionado = alvo_escolhido
665
- else:
666
- # fallback só com setas (sem digitar): vai ao topo e desce checando
667
- send_keys('{HOME}')
668
- vistos = set()
669
- for _ in range(60):
670
- atual = tipo_cobranca.window_text().strip()
671
- if atual.lower() in (o.lower() for o in opcoes):
672
- send_keys('{ENTER}')
673
- selecionado = atual
674
- break
675
- if atual.lower() in vistos:
676
- # deu a volta
677
- send_keys('{ESC}')
678
- break
679
- vistos.add(atual.lower())
680
- send_keys('{DOWN}')
767
+ console.print(f"[PAGAMENTOS] Tipo de cobrança selecionado via navegação por setas: '{selecionado}'", style="bold green")
768
+ break
681
769
 
682
- # (opcional) validação dura
683
- if not selecionado or selecionado.lower() not in (o.lower() for o in opcoes):
684
- raise RuntimeError(f"Não consegui selecionar uma opção válida. Ficou: '{tipo_cobranca.window_text().strip()}'")
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
685
773
 
686
- print("Selecionado:", selecionado)
687
-
688
- dt_vencimento_nota = nota.get("dataVencimento") # vem como '2025-09-26'
689
- data_atual = datetime.now().date()
774
+ vistos.add(atual_lower)
775
+ send_keys('{DOWN}')
690
776
 
691
- # Converte para date (formato yyyy-mm-dd → ISO)
692
- data_vencimento = datetime.strptime(dt_vencimento_nota, "%Y-%m-%d").date()
777
+ erro_tipo = tipo_cobranca.window_text().strip()
778
+ erro_tipo_lower = erro_tipo.lower()
693
779
 
694
- # Se o vencimento for hoje ou já passou, joga para próximo dia útil
695
- if data_vencimento <= data_atual:
696
- data_vencimento = data_atual + timedelta(days=1)
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
785
+ break
786
+
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}'")
793
+
794
+ console.print(f"[PAGAMENTOS] Tipo de cobrança final selecionado: {erro_tipo}", style="bold green")
795
+
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()
697
803
 
698
- # Ajusta para cair só em dias úteis
699
- while data_vencimento.weekday() >= 5: # 5 = sábado, 6 = domingo
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:
700
808
  data_vencimento += timedelta(days=1)
701
809
 
702
- # Converter para string (formato brasileiro dd/mm/yyyy)
703
810
  data_vencimento_str = data_vencimento.strftime("%d/%m/%Y")
704
- print("Novo vencimento:", data_vencimento_str)
705
-
706
- # Inserir no campo
707
- data_venc = panel_TTabSheet.child_window(
708
- class_name="TDBIEditDate", found_index=0
709
- )
811
+ console.print(f"[PAGAMENTOS] Nova data de vencimento calculada: {data_vencimento_str}", style="bold green")
710
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)
711
815
  data_venc.set_edit_text(data_vencimento_str)
712
816
 
713
- console.print(f"Incluindo registro...\n")
817
+ console.print("[PAGAMENTOS] Incluindo registro de parcela (delete + inclui novamente)...", style="bold cyan")
818
+
819
+ try:
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")
714
851
  try:
715
- inserir_registro = pyautogui.locateOnScreen("assets\\entrada_notas\\IncluirRegistro.png", confidence=0.8)
716
- # inserir_registro = pyautogui.locateOnScreen(r"C:\Users\automatehub\Documents\GitHub\worker-automate-hub\assets\entrada_notas\IncluirRegistro.png", confidence=0.8)
852
+ inserir_registro = pyautogui.locateOnScreen(fr"{BASE_PATH}\IncluirRegistro.png", confidence=0.8)
717
853
  pyautogui.click(inserir_registro)
854
+ console.print("[PAGAMENTOS] Botão de 'Incluir Registro' clicado via imagem com sucesso.", style="bold green")
718
855
  except Exception as e:
719
856
  console.print(
720
- 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"
721
859
  )
722
860
  await incluir_registro()
861
+ console.print("[PAGAMENTOS] Fallback incluir_registro() executado.", style="cyan")
723
862
 
724
863
  await worker_sleep(10)
725
-
726
- console.print(
727
- "Verificando a existencia de POP-UP de Itens que Ultrapassam a Variação Máxima de Custo ...\n"
728
- )
729
- itens_variacao_maxima = await is_window_open_by_class(
730
- "TFrmTelaSelecao", "TFrmTelaSelecao"
731
- )
732
- if itens_variacao_maxima["IsOpened"] == True:
733
- app = Application().connect(class_name="TFrmTelaSelecao")
734
- main_window = app["TFrmTelaSelecao"]
735
- send_keys("%o")
736
864
 
737
- await worker_sleep(2)
738
- console.print(
739
- "Verificando a existencia de Warning informando que a Soma dos pagamentos não bate com o valor da nota. ...\n"
740
- )
741
- app = Application().connect(class_name="TFrmNotaFiscalEntrada")
742
- 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")
743
867
 
744
868
  try:
745
- warning_pop_up_pagamentos = main_window.child_window(
746
- class_name="TMessageForm", title="Warning"
747
- )
748
- except:
749
- warning_pop_up_pagamentos = None
750
-
751
- if warning_pop_up_pagamentos.exists():
752
- console.print(
753
- "Erro: Warning informando que a Soma dos pagamentos não bate com o valor da nota. ...\n"
754
- )
755
- return RpaRetornoProcessoDTO(
756
- sucesso=False,
757
- retorno=f"A soma dos pagamentos não bate com o valor da nota.",
758
- status=RpaHistoricoStatusEnum.Falha,
759
- tags=[RpaTagDTO(descricao=RpaTagEnum.Negocio)]
760
- )
761
- else:
762
- console.print(
763
- "Warning informando que a Soma dos pagamentos não bate com o valor da nota não existe ...\n"
764
- )
765
-
766
- max_attempts = 7
767
- i = 0
768
- aguarde_rateio_despesa = True
769
-
770
- while i < max_attempts:
771
- await worker_sleep(3)
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")
772
882
 
773
- from pywinauto import Desktop
883
+ await worker_sleep(2)
774
884
 
775
- for window in Desktop(backend="uia").windows():
776
- if "Rateio" in window.window_text():
777
- aguarde_rateio_despesa = False
778
- console.print(
779
- "A janela 'Rateio da Despesas' foi encontrada. Continuando para andamento do processo...\n"
780
- )
781
- 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
782
894
 
783
- if not aguarde_rateio_despesa:
784
- break
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
785
903
 
786
- i += 1
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")
787
916
 
788
- 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")
789
924
  return RpaRetornoProcessoDTO(
790
925
  sucesso=False,
791
- 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.",
792
927
  status=RpaHistoricoStatusEnum.Falha,
793
928
  tags=[RpaTagDTO(descricao=RpaTagEnum.Tecnico)]
794
929
  )
795
930
 
931
+ console.print("[RATEIO] Chamando função rateio_despesa()...", style="bold cyan")
796
932
  despesa_rateio_work = await rateio_despesa(empresaCodigo)
797
- if despesa_rateio_work.sucesso == True:
933
+ if despesa_rateio_work.sucesso:
798
934
  console.log(despesa_rateio_work.retorno, style="bold green")
799
935
  else:
936
+ console.print("[RATEIO] Falha ao executar rateio_despesa.", style="bold red")
800
937
  return RpaRetornoProcessoDTO(
801
938
  sucesso=False,
802
939
  retorno=despesa_rateio_work.retorno,
@@ -804,86 +941,80 @@ async def opex_capex(task: RpaProcessoEntradaDTO) -> RpaRetornoProcessoDTO:
804
941
  tags=despesa_rateio_work.tags
805
942
  )
806
943
 
807
- # 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")
808
945
  await worker_sleep(15)
809
946
  warning_pop_up = await is_window_open("Warning")
810
- if warning_pop_up["IsOpened"] == True:
811
- app = Application().connect(title="Warning")
812
- main_window = app["Warning"]
813
- main_window.set_focus()
814
-
815
- console.print(f"Obtendo texto do Warning...\n")
816
- 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()
817
952
 
818
- window_rect = main_window.rectangle()
953
+ window_rect = win_w.rectangle()
819
954
  screenshot = pyautogui.screenshot(
820
- region=(
821
- window_rect.left,
822
- window_rect.top,
823
- window_rect.width(),
824
- window_rect.height(),
825
- )
955
+ region=(window_rect.left, window_rect.top, window_rect.width(), window_rect.height())
826
956
  )
827
957
  username = getpass.getuser()
828
- 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"
829
959
  screenshot.save(path_to_png)
830
- 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")
831
961
 
832
- console.print(
833
- f"Preparando a imagem para maior resolução e assertividade no OCR...\n"
834
- )
835
962
  image = Image.open(path_to_png)
836
963
  image = image.convert("L")
837
964
  enhancer = ImageEnhance.Contrast(image)
838
965
  image = enhancer.enhance(2.0)
839
966
  image.save(path_to_png)
840
- console.print(f"Imagem preparada com sucesso...\n")
841
- console.print(f"Realizando OCR...\n")
967
+ console.print("[FINALIZAÇÃO] Imagem preparada. Iniciando OCR...", style="cyan")
842
968
  captured_text = pytesseract.image_to_string(Image.open(path_to_png))
843
- console.print(
844
- f"Texto Full capturado {captured_text}...\n"
845
- )
969
+ console.print(f"[FINALIZAÇÃO] Texto capturado do Warning: {captured_text}", style="bold green")
846
970
  os.remove(path_to_png)
971
+ console.print("[FINALIZAÇÃO] Arquivo de imagem do Warning removido.", style="cyan")
972
+
847
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")
848
975
  return RpaRetornoProcessoDTO(
849
- sucesso=False,
850
- retorno=f"Filial: {empresaCodigo} está com o livro fechado ou encerrado, verificar com o setor fiscal",
851
- status=RpaHistoricoStatusEnum.Falha,
852
- 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)]
853
980
  )
854
981
  else:
982
+ console.print("[FINALIZAÇÃO] Warning não mapeado. Retornando como erro técnico com mensagem completa do OCR.", style="bold red")
855
983
  return RpaRetornoProcessoDTO(
856
- sucesso=False,
857
- retorno=f"Warning não mapeado para seguimento do robo, mensagem: {captured_text}",
858
- status=RpaHistoricoStatusEnum.Falha,
859
- 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)]
860
988
  )
861
989
 
862
990
  await worker_sleep(3)
863
- # 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")
864
993
  nf_imported = await check_nota_importada(dados_nf[0].get("chaveNfe"))
865
- 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:
866
996
  await worker_sleep(3)
867
- console.print("\nVerifica se a nota ja foi lançada...")
868
- nf_chave_acesso = int(dados_nf[0].get("chaveNfe"))
869
- 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")
870
1001
  if status_nf_emsys.get("status") == "Lançada":
871
- 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")
872
1003
  return RpaRetornoProcessoDTO(
873
1004
  sucesso=True,
874
1005
  retorno="Nota Lançada com sucesso!",
875
1006
  status=RpaHistoricoStatusEnum.Sucesso,
876
1007
  )
877
1008
  else:
878
- 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")
879
1010
  return RpaRetornoProcessoDTO(
880
1011
  sucesso=False,
881
- 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}",
882
1013
  status=RpaHistoricoStatusEnum.Falha,
883
1014
  tags=[RpaTagDTO(descricao=RpaTagEnum.Negocio)]
884
1015
  )
885
1016
  else:
886
- 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")
887
1018
  return RpaRetornoProcessoDTO(
888
1019
  sucesso=False,
889
1020
  retorno=f"Erro ao lançar nota, erro: {nf_imported.retorno}",
@@ -892,7 +1023,7 @@ async def opex_capex(task: RpaProcessoEntradaDTO) -> RpaRetornoProcessoDTO:
892
1023
  )
893
1024
 
894
1025
  except Exception as ex:
895
- observacao = f"Erro Processo Entrada de Notas: {str(ex)}"
1026
+ observacao = f"[ERRO GERAL] Erro Processo Entrada de Notas: {str(ex)}"
896
1027
  logger.error(observacao)
897
1028
  console.print(observacao, style="bold red")
898
1029
  return RpaRetornoProcessoDTO(
@@ -903,5 +1034,13 @@ async def opex_capex(task: RpaProcessoEntradaDTO) -> RpaRetornoProcessoDTO:
903
1034
  )
904
1035
 
905
1036
  finally:
906
- # Deleta o xml
907
- await delete_xml(numero_nota)
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")