worker-automate-hub 0.5.805__py3-none-any.whl → 0.5.807__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.
@@ -577,103 +577,86 @@ async def abertura_livros_fiscais(task: RpaProcessoEntradaDTO) -> RpaRetornoProc
577
577
 
578
578
  await worker_sleep(2)
579
579
 
580
- desk = Desktop(backend="win32")
581
- dlg = None
582
- t_end = time.time() + 8.0 # até 8s procurando a janela
583
- while time.time() < t_end:
580
+ # flag para controlar se é a primeira vez
581
+ primeira_confirmacao = True
582
+
583
+ while True:
584
+ janela_aberta = False
585
+
586
+ # 1. Verifica se a imagem apareceu e clica em 'Sim' na janela "Informação"
584
587
  try:
585
- # variações: Aviso | Atenção | Erro
586
- wins = desk.windows(
587
- title_re=".*(Aviso|Aten[cç][aã]o|Erro).*", visible_only=True
588
- )
589
- if wins:
590
- dlg = wins[0]
591
- break
592
- except Exception:
593
- pass
594
- time.sleep(0.25)
588
+ if pyautogui.locateOnScreen(imagem, confidence=0.9):
589
+ print("Imagem 'livros_incluidos' apareceu na tela.")
590
+ try:
591
+ app_info = Application().connect(title="Informação", timeout=5)
592
+ info_window = app_info["Informação"]
593
+ info_window.set_focus()
594
+ console.print("Clicando em 'Sim' na janela Informação...")
595
+ info_window.child_window(class_name="Button", found_index=0).click_input()
596
+ except Exception as e:
597
+ print(f"Erro ao clicar em 'Sim' na janela Informação: {e}")
598
+ except Exception as e:
599
+ print(f"[Erro ao procurar imagem]: {e}")
595
600
 
596
- if dlg:
597
- console.print(
598
- "Janela 'Aviso' detectada. Capturando texto e screenshot..."
599
- )
601
+ # Verifica se a janela TMsgBox de aviso está aberta
602
+ try:
603
+ app_msgbox = Application().connect(class_name="TMsgBox", timeout=10)
604
+ box = app_msgbox["TMsgBox"]
605
+ print("Janela 'TMsgBox' encontrada.")
606
+ box.set_focus()
607
+ box.child_window(class_name="TBitBtn", found_index=0).click_input()
608
+ print("Clicou no botão 'TBitBtn'.")
609
+ except ElementNotFoundError:
610
+ pass
611
+ except Exception as e:
612
+ print(f"[Erro ao procurar/clicar na TMsgBox]: {e}")
600
613
 
601
- # === 2) Captura de screenshot da janela ===
614
+ # 2. Verifica e trata janela de confirmação TMessageForm
602
615
  try:
603
- # pasta de prints (ajuste se quiser outra)
604
- prints_dir = os.path.join(os.getcwd(), "prints")
605
- os.makedirs(prints_dir, exist_ok=True)
606
- ts = datetime.now().strftime("%Y%m%d_%H%M%S")
607
- screenshot_path = os.path.join(prints_dir, f"aviso_{ts}.png")
608
- dlg.set_focus()
609
- img = dlg.capture_as_image()
610
- img.save(screenshot_path)
611
- console.print(f"Screenshot salvo: {screenshot_path}")
616
+ app_msg = Application().connect(class_name="TMessageForm", timeout=2)
617
+ form = app_msg["TMessageForm"]
618
+ console.print("Janela de confirmação 'TMessageForm' encontrada.")
619
+ form.set_focus()
620
+
621
+ idx = 1 if primeira_confirmacao else 0
622
+ try:
623
+ form.child_window(class_name="TButton", found_index=idx).click_input()
624
+ print(f"Clicou no botão de confirmação (found_index={idx}).")
625
+ primeira_confirmacao = False # nas próximas vezes será 0
626
+ except Exception as e:
627
+ print(f"[Falha ao clicar no botão found_index={idx}]: {e}")
628
+
629
+ except ElementNotFoundError:
630
+ pass
612
631
  except Exception as e:
613
- screenshot_path = None
614
- console.print(f"Falha ao salvar screenshot do 'Aviso': {e}")
632
+ print(f"[Erro ao procurar/clicar na TMessageForm]: {e}")
615
633
 
616
- # === 3) Lê todo o texto da janela ===
617
- texto_aviso = ""
634
+ await worker_sleep(5)
635
+
636
+ # 3. Verifica se a janela do relatório está aberta
618
637
  try:
619
- partes = []
620
- for ctrl in dlg.descendants():
621
- try:
622
- t = ctrl.window_text()
623
- if t and t.strip():
624
- partes.append(t.strip())
625
- except Exception:
626
- pass
627
- texto_aviso = " ".join(
628
- dict.fromkeys(partes)
629
- ) # remove duplicados mantendo ordem
630
- console.print(f"Texto do Aviso: {texto_aviso}")
638
+ app_report = Application().connect(class_name="TFrmPreviewRelatorio", timeout=2)
639
+ janela = app_report["TFrmPreviewRelatorio"]
640
+ print("Janela 'TFrmPreviewRelatorio' encontrada.")
641
+ janela_aberta = True
642
+ except ElementNotFoundError:
643
+ pass
631
644
  except Exception as e:
632
- console.print(f"Falha ao coletar texto do 'Aviso': {e}")
645
+ print(f"[Erro ao procurar TFrmPreviewRelatorio]: {e}")
633
646
 
634
- # === 4) Validação do conteúdo (edite/adicione frases-chave conforme seu caso) ===
635
- FRASES_ERRO = [
636
- "O período para apuração informado",
637
- "situação diferente de confirmado",
638
- ]
647
+ # Se encontrou a janela de relatório, sai
648
+ if janela_aberta:
649
+ print("Relatório carregado. Saindo do loop.")
650
+ break
639
651
 
640
- contem_msg_erro = any(
641
- frase.lower() in texto_aviso.lower() for frase in FRASES_ERRO
642
- )
652
+ # Verifica tempo limite
653
+ if time.time() - inicio > tempo_limite:
654
+ print("Tempo esgotado. Relatório não carregado.")
655
+ break
656
+
657
+ print("Aguardando janela de relatório... (verificando novas confirmações se houver)")
658
+ time.sleep(intervalo)
643
659
 
644
- if contem_msg_erro:
645
- console.print(
646
- "Confirmação de erro pelo texto da janela 'Aviso'. Retornando falha."
647
- )
648
- retorno_msg = "Erro ao Incluir apuração."
649
- if texto_aviso:
650
- retorno_msg += f" Detalhe: {texto_aviso}"
651
- if screenshot_path:
652
- retorno_msg += f" | Print: {screenshot_path}"
653
-
654
- return RpaRetornoProcessoDTO(
655
- sucesso=False,
656
- retorno=retorno_msg,
657
- status=RpaHistoricoStatusEnum.Falha,
658
- tags=[RpaTagDTO(descricao=RpaTagEnum.Negocio)],
659
- )
660
- else:
661
- console.print(
662
- "Janela 'Aviso' não contém mensagem de erro mapeada. Seguindo fluxo."
663
- )
664
- # (Opcional) você pode clicar no 'OK' e continuar:
665
- try:
666
- # tenta clicar em botão OK se existir
667
- for c in dlg.descendants():
668
- try:
669
- if c.window_text().strip().lower() in ("ok", "&ok"):
670
- c.click_input()
671
- break
672
- except Exception:
673
- pass
674
- except Exception:
675
- pass
676
- # não retorna aqui; deixa seguir para sucesso
677
660
 
678
661
  # === 5) Se não houve 'Aviso' com erro mapeado, considera sucesso ===
679
662
  console.print("Nenhum erro confirmado. Fluxo OK.")
@@ -12,12 +12,12 @@ 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
- sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..","..","..")))
20
+ # sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..","..","..")))
21
21
  from worker_automate_hub.api.ahead_service import save_xml_to_downloads
22
22
  from worker_automate_hub.api.client import (
23
23
  get_config_by_name,
@@ -471,6 +471,7 @@ async def opex_capex(task: RpaProcessoEntradaDTO) -> RpaRetornoProcessoDTO:
471
471
 
472
472
  # Clicar em itens da nota
473
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"
474
475
 
475
476
  # Tenta localizar a imagem na tela
476
477
  while True:
@@ -547,6 +548,11 @@ async def opex_capex(task: RpaProcessoEntradaDTO) -> RpaRetornoProcessoDTO:
547
548
  send_keys("{ENTER}")
548
549
  except Exception as e:
549
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%")
550
556
 
551
557
  # Clicar em alterar
552
558
  main_window.child_window(class_name="TDBIBitBtn", found_index=3).click()
@@ -585,27 +591,99 @@ async def opex_capex(task: RpaProcessoEntradaDTO) -> RpaRetornoProcessoDTO:
585
591
 
586
592
  panel_TabPagamento = panel_TTabSheet.child_window(title="Pagamento")
587
593
 
588
- tipo_cobranca = panel_TTabSheet.child_window(
589
- class_name="TDBIComboBox", found_index=0
590
- )
591
- tipo_cobranca.click()
592
- # Lista de opções em ordem de prioridade
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
593
598
  opcoes = [
594
599
  "BANCO DO BRASIL BOLETO FIDC",
595
600
  "BANCO DO BRASIL BOLETO",
596
- "BOLETO"
601
+ "BOLETO",
597
602
  ]
598
603
 
599
- # Vamos percorrer o combo com setas
600
- max_tentativas = 20 # evita loop infinito
601
- for _ in range(max_tentativas):
602
- texto_atual = tipo_cobranca.window_text().strip()
603
- if any(opcao.lower() == texto_atual.lower() for opcao in opcoes):
604
- send_keys("{ENTER}")
605
- break
606
- send_keys("{DOWN}")
607
-
608
- await worker_sleep(3)
604
+ # 1) Tenta .select() direto (não digita nada)
605
+ selecionado = None
606
+ for alvo in opcoes:
607
+ try:
608
+ tipo_cobranca.select(alvo)
609
+ if tipo_cobranca.window_text().strip().lower() == alvo.lower():
610
+ selecionado = alvo
611
+ break
612
+ except Exception:
613
+ pass
614
+
615
+ # 2) Abre a LISTA e seleciona o item exato (sem digitar)
616
+ 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:
648
+ break
649
+
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}')
658
+ 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}')
681
+
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()}'")
685
+
686
+ print("Selecionado:", selecionado)
609
687
 
610
688
  dt_vencimento_nota = nota.get("dataVencimento") # vem como '2025-09-26'
611
689
  data_atual = datetime.now().date()
@@ -634,10 +712,8 @@ async def opex_capex(task: RpaProcessoEntradaDTO) -> RpaRetornoProcessoDTO:
634
712
 
635
713
  console.print(f"Incluindo registro...\n")
636
714
  try:
637
- ASSETS_PATH = "assets"
638
- inserir_registro = pyautogui.locateOnScreen(
639
- "assets\\entrada_notas\\IncluirRegistro.png", confidence=0.8
640
- )
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)
641
717
  pyautogui.click(inserir_registro)
642
718
  except Exception as e:
643
719
  console.print(
@@ -830,4 +906,3 @@ async def opex_capex(task: RpaProcessoEntradaDTO) -> RpaRetornoProcessoDTO:
830
906
  # Deleta o xml
831
907
  await delete_xml(numero_nota)
832
908
 
833
-
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: worker-automate-hub
3
- Version: 0.5.805
3
+ Version: 0.5.807
4
4
  Summary: Worker Automate HUB é uma aplicação para automatizar rotinas de RPA nos ambientes Argenta.
5
5
  Author: Joel Paim
6
6
  Requires-Python: >=3.12,<4.0
@@ -36,7 +36,7 @@ worker_automate_hub/models/dto/rpa_sap_dto.py,sha256=eovdvKCtVIhRct3PL98KjsdlngL
36
36
  worker_automate_hub/models/dto/rpa_sistema_dto.py,sha256=sLkmJei8x6sl-1-IXUKDmYQuKx0sotYQREPyhQqPmRg,161
37
37
  worker_automate_hub/tasks/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
38
38
  worker_automate_hub/tasks/jobs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
39
- worker_automate_hub/tasks/jobs/abertura_livros_fiscais.py,sha256=4HzIhBWNfCWUMvZZ3VmQ7atytkcODQliV7XeZXBpMgo,27828
39
+ worker_automate_hub/tasks/jobs/abertura_livros_fiscais.py,sha256=3455qiEsrjMSUZqsOOl-mCbjGv8M2t-x3EtXEzpiuls,27309
40
40
  worker_automate_hub/tasks/jobs/coleta_dje_process.py,sha256=UkLWTC5Ub2qBb0yY-8IZ0DLLOVJOfNTq_z9krx_t25Q,29476
41
41
  worker_automate_hub/tasks/jobs/conexao_rdp.py,sha256=S6QC4xhuo0pB5FjaUJZNMm1LIgEjpjifReCTBDqxH-U,11719
42
42
  worker_automate_hub/tasks/jobs/cte_manual.py,sha256=JucHpRMjMiy-QEJ0wtFnytLpN53tKXgCDI05nGLGclU,603
@@ -88,7 +88,7 @@ worker_automate_hub/tasks/jobs/lancamento_rateio.py,sha256=0cvbpuJiHl5mca5gpZudX
88
88
  worker_automate_hub/tasks/jobs/login_emsys.py,sha256=dO9S027qRTtjOfytF6IWO-m6hDld8kZqOVAsn91l1YA,5684
89
89
  worker_automate_hub/tasks/jobs/login_emsys_versao_especifica.py,sha256=_6CFh79eaW9KdPGR6FMV01ASPjJzNzzBK1MvC_uiSOo,5625
90
90
  worker_automate_hub/tasks/jobs/notas_faturamento_sap.py,sha256=p6tVE027FHHXBxt2sIDxqLInpf_0wS-8TcACnS34p7w,13961
91
- worker_automate_hub/tasks/jobs/opex_capex.py,sha256=biSi3BeUqhl3OqRhqnZMbBp1u8QgDFfcBqS_6YOt5z4,33172
91
+ worker_automate_hub/tasks/jobs/opex_capex.py,sha256=hp0B7QTTO1TTQR8xVyCxpYgwixglipx3CKT9ZDvA4ao,36879
92
92
  worker_automate_hub/tasks/jobs/playground.py,sha256=7vWDg9DwToHwGJ6_XOa8TQ6LmfRV5Qz2TaOV3q3P9sA,1918
93
93
  worker_automate_hub/tasks/jobs/sped_fiscal.py,sha256=Zsq-IwKxA0b2tikO6Rri4WXVj10jK-Jd0-gxk8yVBH0,31064
94
94
  worker_automate_hub/tasks/jobs/transferencias.py,sha256=5TIktufkvUPnVTR2gf7GFQJ5KQP6PWnmoWiE08WiVDQ,46191
@@ -103,7 +103,7 @@ worker_automate_hub/utils/updater.py,sha256=en2FCGhI8aZ-JNP3LQm64NJDc4awCNW7UhbV
103
103
  worker_automate_hub/utils/util.py,sha256=noQRUSAjRnoDb1c4iMZ5eoyrNp59a8T9K78MHhalASw,210255
104
104
  worker_automate_hub/utils/utils_nfe_entrada.py,sha256=F7jk95LpDwl5WfaQXahCA5yDdnySnWdctDqczHXwGqE,38195
105
105
  worker_automate_hub/worker.py,sha256=zEnYUrm5kY2cHbbee15QJkwkx4euD2SB2zRvUIbjS90,6850
106
- worker_automate_hub-0.5.805.dist-info/entry_points.txt,sha256=sddyhjx57I08RY8X7UxcTpdoOsWULAWNKN9Xr6pp_Kw,54
107
- worker_automate_hub-0.5.805.dist-info/METADATA,sha256=LiSvpCGDuFf_Z0Rpccp9JkG1kb4r3ylseyEbes7jnFo,3100
108
- worker_automate_hub-0.5.805.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
109
- worker_automate_hub-0.5.805.dist-info/RECORD,,
106
+ worker_automate_hub-0.5.807.dist-info/entry_points.txt,sha256=sddyhjx57I08RY8X7UxcTpdoOsWULAWNKN9Xr6pp_Kw,54
107
+ worker_automate_hub-0.5.807.dist-info/METADATA,sha256=NWOK6pfCQIyr7MK4SshrBxOwipy2sJhV3Gxo4hz23BY,3100
108
+ worker_automate_hub-0.5.807.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
109
+ worker_automate_hub-0.5.807.dist-info/RECORD,,