worker-automate-hub 0.5.737__py3-none-any.whl → 0.5.738__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.
@@ -1,5 +1,7 @@
1
1
  from decimal import ROUND_HALF_UP, Decimal
2
2
  import threading
3
+ from typing import Optional
4
+ import aiohttp
3
5
 
4
6
  import aiohttp
5
7
  import requests
@@ -493,32 +495,24 @@ async def get_valor_remessa_cobranca(date: str):
493
495
 
494
496
  async def get_status_nf_emsys(chave: int):
495
497
  """
496
- Procura o status de nota fiscal no EMSYS.
497
-
498
- Args:
499
- chave (int): Chave de acesso a NF.
500
-
501
- Returns:
502
- dict: Contendo o chave de acesso e status de processamento da nota.
503
-
504
- Raises:
505
- Exception: Se houver um erro ao comunicar com o endpoint do Simplifica.
498
+ Procura o status de nota fiscal no EMSYS.
506
499
  """
507
500
  env_config, _ = load_env_config()
508
501
 
509
502
  url = f"{env_config['API_BASE_URL']}/emsys/consulta-status-nota?chaveNfe={chave}"
510
-
511
503
  headers_basic = {"Authorization": f"Basic {env_config['API_AUTHORIZATION']}"}
512
504
  timeout = aiohttp.ClientTimeout(total=600)
513
505
 
514
506
  try:
507
+ timeout = aiohttp.ClientTimeout(total=600) # aguarda até 10 minutos
515
508
  async with aiohttp.ClientSession(
516
- connector=aiohttp.TCPConnector(verify_ssl=True), timeout=timeout
509
+ connector=aiohttp.TCPConnector(verify_ssl=True),
510
+ timeout=timeout
517
511
  ) as session:
518
512
  async with session.get(url, headers=headers_basic) as response:
519
513
  if response.status != 200:
520
514
  raise Exception(
521
- f"Erro ao comunicar com endpoint do Simplifica: {response.text}"
515
+ f"Erro ao comunicar com endpoint do Simplifica: {await response.text()}"
522
516
  )
523
517
  data = await response.json()
524
518
  if not data or not isinstance(data, dict):
@@ -526,17 +520,139 @@ async def get_status_nf_emsys(chave: int):
526
520
  f"Erro ao comunicar com endpoint do Simplifica: {data}"
527
521
  )
528
522
  log_msg = f"\nSucesso ao procurar {data}.\n"
529
- console.print(
530
- log_msg,
531
- style="bold green",
532
- )
523
+ console.print(log_msg, style="bold green")
533
524
  logger.info(log_msg)
534
525
  return data
535
526
 
536
527
  except Exception as e:
537
528
  err_msg = f"Erro ao comunicar com endpoint do Simplifica: {e}"
538
- console.print(f"\n{err_msg}\n", style="bold green")
539
- logger.info(err_msg)
529
+ console.print(f"\n{err_msg}\n", style="bold red")
530
+ logger.error(err_msg)
531
+
532
+ async def get_dados_nf_emsys(
533
+ chave: Optional[int] = None,
534
+ numero_nota: Optional[int] = None,
535
+ serie_nota: Optional[int] = None,
536
+ filial_nota: Optional[int] = None
537
+ ):
538
+ """
539
+ Consulta a NF no EMSYS (ahead-nota) e retorna os campos essenciais:
540
+ empresaCodigo, numeroDoCfop e cfopProduto dentro de itens.
541
+
542
+ Args:
543
+ chave (int, opcional): Chave de acesso da NF.
544
+ numero_nota (int, opcional): Número da NF.
545
+ serie_nota (int, opcional): Série da NF (obrigatória se numero_nota for informado).
546
+ filial_nota (int, opcional): Filial da NF (obrigatória se numero_nota for informado).
547
+
548
+ Returns:
549
+ list[dict]: Lista de notas no formato esperado.
550
+ """
551
+ env_config, _ = load_env_config()
552
+
553
+ url = f"{env_config['API_BASE_URL']}/ahead-nota/find-by-number-nfe"
554
+
555
+ params = {}
556
+
557
+ # Caso 1: veio a chave
558
+ if chave is not None:
559
+ params["chaveNfe"] = chave
560
+
561
+ # Caso 2: veio numero_nota → exige serie e filial
562
+ elif numero_nota is not None:
563
+ if serie_nota is None or filial_nota is None:
564
+ raise ValueError("Para buscar por número da nota é obrigatório informar também 'serie_nota' e 'filial_nota'.")
565
+ params["numeroNfe"] = numero_nota
566
+ params["serieNfe"] = serie_nota
567
+ params["empresaCodigo"] = filial_nota
568
+
569
+ else:
570
+ raise ValueError("É necessário informar 'chave' ou ('numero_nota' + 'serie_nota' + 'filial_nota').")
571
+
572
+ headers_basic = {"Authorization": f"Basic {env_config['API_AUTHORIZATION']}"}
573
+
574
+ try:
575
+ async with aiohttp.ClientSession(
576
+ connector=aiohttp.TCPConnector(verify_ssl=True)
577
+ ) as session:
578
+ async with session.get(url, headers=headers_basic, params=params) as response:
579
+ if response.status != 200:
580
+ raise Exception(
581
+ f"Erro ao comunicar com endpoint do Simplifica: {await response.text()}"
582
+ )
583
+
584
+ data = await response.json()
585
+
586
+ if not data:
587
+ raise Exception("Não foi possível buscar os dados da nota (ahead_nota).")
588
+
589
+ if isinstance(data, dict):
590
+ data = [data]
591
+
592
+ resultado = []
593
+ for nota in data:
594
+ resultado.append({
595
+ "chaveNfe": nota.get("chaveNfe"),
596
+ "numeroDoCfop": nota.get("numeroDoCfop"),
597
+ "naturezaNota": nota.get("naturezaNota"),
598
+ "empresa": nota.get("empresa"),
599
+ "fornecedorCnpj": nota.get("fornecedorCnpj"),
600
+ "fornecedorNome": nota.get("fornecedorNome"),
601
+ "numeroNfe": nota.get("numeroNfe"),
602
+ "valorNfe": nota.get("valorNfe"),
603
+ "dataEmissao": nota.get("dataEmissao"),
604
+ "empresaCodigo": nota.get("empresaCodigo"),
605
+ "dataVencimento": nota.get("dataVencimento"),
606
+ "statusSituacao": nota.get("statusSituacao"),
607
+ "statusRebUnidade": nota.get("statusRebUnidade"),
608
+ "statusListarNotas": nota.get("statusListarNotas"),
609
+ "existeDespesa": nota.get("existeDespesa"),
610
+ "observacao": nota.get("observacao"),
611
+ "createdAt": nota.get("createdAt"),
612
+ "updatedAt": nota.get("updatedAt"),
613
+ "infCpl": nota.get("infCpl"),
614
+ "recebimentoFisico": nota.get("recebimentoFisico"),
615
+ "serieNfe": nota.get("serieNfe"),
616
+ "statusLancamento": nota.get("statusLancamento"),
617
+ "dataEntrada": nota.get("dataEntrada"),
618
+ "codPessoaFornecedor": nota.get("codPessoaFornecedor"),
619
+ "locked": nota.get("locked"),
620
+ "itens": [
621
+ {
622
+ "uuidNotaItem": item.get("uuidNotaItem"),
623
+ "chaveNfe": item.get("chaveNfe"),
624
+ "codigoProduto": item.get("codigoProduto"),
625
+ "descricaoProduto": item.get("descricaoProduto"),
626
+ "ncmsh": item.get("ncmsh"),
627
+ "ocst": item.get("ocst"),
628
+ "cfopProduto": item.get("cfopProduto"),
629
+ "unidadeMedida": item.get("unidadeMedida"),
630
+ "qtd": item.get("qtd"),
631
+ "valorUnitario": item.get("valorUnitario"),
632
+ "valorTotal": item.get("valorTotal"),
633
+ "bCalculoIcms": item.get("bCalculoIcms"),
634
+ "valorIcms": item.get("valorIcms"),
635
+ "valorIpi": item.get("valorIpi"),
636
+ "aliquotaIcms": item.get("aliquotaIcms"),
637
+ "aliquotaIpi": item.get("aliquotaIpi"),
638
+ "createdAt": item.get("createdAt"),
639
+ "updatedAt": item.get("updatedAt"),
640
+ "pedidoCompraXped": item.get("pedidoCompraXped"),
641
+ "pedidoCompraItemPed": item.get("pedidoCompraItemPed"),
642
+ "codItem": item.get("codItem"),
643
+ "desItem": item.get("desItem"),
644
+ "indBloqueadoCompra": item.get("indBloqueadoCompra"),
645
+ "indItemAtivo": item.get("indItemAtivo")
646
+ }
647
+ for item in nota.get("itens", [])
648
+ ]
649
+ })
650
+
651
+ return resultado
652
+
653
+ except Exception as e:
654
+ raise Exception(f"Erro ao comunicar com endpoint do Simplifica: {e}")
655
+
540
656
 
541
657
 
542
658
  async def get_status_cte_emsys(chave: int):
@@ -0,0 +1,832 @@
1
+ import difflib
2
+ import getpass
3
+ import os
4
+ import re
5
+ import warnings
6
+ import time
7
+ import uuid
8
+ from datetime import datetime, timedelta
9
+ import pyautogui
10
+ import pytesseract
11
+ import win32clipboard
12
+ from PIL import Image, ImageEnhance
13
+ from pywinauto.application import Application
14
+ from pywinauto.keyboard import send_keys
15
+ from pywinauto.timings import wait_until
16
+ from pywinauto_recorder.player import set_combobox
17
+ from rich.console import Console
18
+ import sys
19
+ import asyncio
20
+ sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..","..","..")))
21
+ from worker_automate_hub.api.ahead_service import save_xml_to_downloads
22
+ from worker_automate_hub.api.client import (
23
+ get_config_by_name,
24
+ get_status_nf_emsys,
25
+ get_dados_nf_emsys,
26
+ )
27
+ from worker_automate_hub.models.dto.rpa_historico_request_dto import (
28
+ RpaHistoricoStatusEnum,
29
+ RpaRetornoProcessoDTO,
30
+ RpaTagDTO,
31
+ RpaTagEnum,
32
+ )
33
+ from worker_automate_hub.models.dto.rpa_processo_entrada_dto import (
34
+ RpaProcessoEntradaDTO,
35
+ )
36
+ from worker_automate_hub.utils.logger import logger
37
+ from worker_automate_hub.utils.util import (
38
+ cod_icms,
39
+ delete_xml,
40
+ error_after_xml_imported,
41
+ get_xml,
42
+ import_nfe,
43
+ incluir_registro,
44
+ is_window_open,
45
+ is_window_open_by_class,
46
+ itens_not_found_supplier,
47
+ kill_all_emsys,
48
+ login_emsys,
49
+ rateio_despesa,
50
+ select_documento_type,
51
+ set_variable,
52
+ tipo_despesa,
53
+ type_text_into_field,
54
+ warnings_after_xml_imported,
55
+ worker_sleep,
56
+ zerar_icms,
57
+ check_nota_importada,
58
+ )
59
+
60
+ pyautogui.PAUSE = 0.5
61
+ pyautogui.FAILSAFE = False
62
+ console = Console()
63
+
64
+ async def get_ultimo_item():
65
+ send_keys("^({END})")
66
+ await worker_sleep(2)
67
+ send_keys("+{F10}")
68
+ await worker_sleep(1)
69
+ send_keys("{DOWN 2}")
70
+ await worker_sleep(1)
71
+ send_keys("{ENTER}")
72
+ await worker_sleep(2)
73
+ app = Application().connect(title="Alteração de Item")
74
+ main_window = app["Alteração de Item"]
75
+ main_window.set_focus()
76
+ edit = main_window.child_window(class_name="TDBIEditCode", found_index=0)
77
+ index_ultimo_item = int(edit.window_text())
78
+ try:
79
+ btn_cancelar = main_window.child_window(title="&Cancelar")
80
+ btn_cancelar.click()
81
+ except Exception as error:
82
+ btn_cancelar = main_window.child_window(title="Cancelar")
83
+ btn_cancelar.click()
84
+ console.print(f"Erro ao realizar get_ultimo_item: {error}")
85
+ await worker_sleep(1)
86
+ return index_ultimo_item
87
+
88
+ async def opex_capex(task: RpaProcessoEntradaDTO) -> RpaRetornoProcessoDTO:
89
+ """
90
+ Processo que realiza entrada de notas no ERP EMSys(Linx).
91
+
92
+ """
93
+ try:
94
+ # Get config from BOF
95
+ config = await get_config_by_name("login_emsys")
96
+ console.print(task)
97
+
98
+ # Seta config entrada na var nota para melhor entendimento
99
+ nota = task.configEntrada
100
+ multiplicador_timeout = int(float(task.sistemas[0].timeout))
101
+ set_variable("timeout_multiplicador", multiplicador_timeout)
102
+
103
+ # Fecha a instancia do emsys - caso esteja aberta
104
+ await kill_all_emsys()
105
+ data_atual = datetime.now().strftime("%d/%m/%Y")
106
+ print(data_atual)
107
+ # Buscar número da nota
108
+ numero_nota = nota.get("numeroNota")
109
+ serie_nota = nota.get("serieNota")
110
+ filial_nota = nota.get("descricaoFilial")
111
+ filial_nota = filial_nota.split("-")[0].strip()
112
+ centro_custo = nota.get("centroCusto")
113
+ centro_custo = centro_custo.split("-")[0].strip().lstrip("0")
114
+
115
+ try:
116
+ dados_nf = await get_dados_nf_emsys(
117
+ numero_nota=numero_nota,
118
+ serie_nota=serie_nota,
119
+ filial_nota=filial_nota
120
+ )
121
+
122
+ # Se a API retornou erro
123
+ if isinstance(dados_nf, dict) and "erro" in dados_nf:
124
+ console.print("Erro retornado pela API:", dados_nf["erro"])
125
+ nf_chave_acesso = None
126
+
127
+ # Se retornou lista mas está vazia
128
+ elif isinstance(dados_nf, list) and not dados_nf:
129
+ console.print("Nenhum dado encontrado para a nota.")
130
+ nf_chave_acesso = None
131
+
132
+ # Se retornou lista com dados
133
+ else:
134
+ nf_chave_acesso = dados_nf[0].get("chaveNfe")
135
+ console.print("Chave da NF:", nf_chave_acesso)
136
+
137
+ except Exception as e:
138
+ console.print("Erro inesperado ao buscar nota:", str(e))
139
+ nf_chave_acesso = None
140
+
141
+ # Download XML
142
+ console.log("Realizando o download do XML..\n")
143
+ await save_xml_to_downloads(nf_chave_acesso)
144
+
145
+ status_nf_emsys = await get_status_nf_emsys(nf_chave_acesso)
146
+
147
+ empresa_codigo = dados_nf[0]["empresaCodigo"]
148
+ cfop = dados_nf[0]["numeroDoCfop"]
149
+ cfops_itens = [item["cfopProduto"] for item in dados_nf[0]["itens"]]
150
+
151
+
152
+
153
+ if status_nf_emsys.get("status") == "Lançada":
154
+ console.print(
155
+ "\\Nota fiscal já lançada, processo finalizado...", style="bold green"
156
+ )
157
+ return RpaRetornoProcessoDTO(
158
+ sucesso=False,
159
+ retorno="Nota fiscal já lançada",
160
+ status=RpaHistoricoStatusEnum.Descartado,
161
+ )
162
+ else:
163
+ console.print("\\Nota fiscal não lançada, iniciando o processo...")
164
+
165
+ app = Application(backend="win32").start("C:\\Rezende\\EMSys3\\EMSys3_29.exe")
166
+ warnings.filterwarnings(
167
+ "ignore",
168
+ category=UserWarning,
169
+ message="32-bit application should be automated using 32-bit Python",
170
+ )
171
+ console.print("\nEMSys iniciando...", style="bold green")
172
+ return_login = await login_emsys(config.conConfiguracao, app, task, filial_origem = empresa_codigo)
173
+
174
+ if return_login.sucesso == True:
175
+ type_text_into_field(
176
+ "Nota Fiscal de Entrada", app["TFrmMenuPrincipal"]["Edit"], True, "50"
177
+ )
178
+ pyautogui.press("enter")
179
+ await worker_sleep(2)
180
+ pyautogui.press("enter")
181
+ console.print(
182
+ f"\nPesquisa: 'Nota Fiscal de Entrada' realizada com sucesso",
183
+ style="bold green",
184
+ )
185
+ else:
186
+ logger.info(f"\nError Message: {return_login.retorno}")
187
+ console.print(f"\nError Message: {return_login.retorno}", style="bold red")
188
+ return return_login
189
+
190
+ await worker_sleep(6)
191
+
192
+ # Procura campo documento
193
+ console.print("Navegando pela Janela de Nota Fiscal de Entrada...\n")
194
+ document_type = await select_documento_type(
195
+ "NOTA FISCAL DE ENTRADA ELETRONICA - DANFE"
196
+ )
197
+ if document_type.sucesso == True:
198
+ console.log(document_type.retorno, style="bold green")
199
+ else:
200
+ return RpaRetornoProcessoDTO(
201
+ sucesso=False,
202
+ retorno=document_type.retorno,
203
+ status=RpaHistoricoStatusEnum.Falha,
204
+ tags=[RpaTagDTO(descricao=RpaTagEnum.Tecnico)]
205
+ )
206
+
207
+ await worker_sleep(4)
208
+
209
+ # Clica em 'Importar-Nfe'
210
+ imported_nfe = await import_nfe()
211
+ if imported_nfe.sucesso == True:
212
+ console.log(imported_nfe.retorno, style="bold green")
213
+ else:
214
+ return RpaRetornoProcessoDTO(
215
+ sucesso=False,
216
+ retorno=imported_nfe.retorno,
217
+ status=RpaHistoricoStatusEnum.Falha,
218
+ tags=[RpaTagDTO(descricao=RpaTagEnum.Tecnico)]
219
+ )
220
+
221
+ await worker_sleep(5)
222
+
223
+ await get_xml(nf_chave_acesso)
224
+
225
+
226
+ await worker_sleep(3)
227
+
228
+ # VERIFICANDO A EXISTENCIA DE WARNINGS
229
+ warning_pop_up = await is_window_open("Warning")
230
+ if warning_pop_up["IsOpened"] == True:
231
+ warning_work = await warnings_after_xml_imported()
232
+ if warning_work.sucesso == True:
233
+ console.log(warning_work.retorno, style="bold green")
234
+ else:
235
+ return RpaRetornoProcessoDTO(
236
+ sucesso=False,
237
+ retorno=warning_work.retorno,
238
+ status=RpaHistoricoStatusEnum.Falha,
239
+ tags=[RpaTagDTO(descricao=RpaTagEnum.Tecnico)]
240
+ )
241
+
242
+ # VERIFICANDO A EXISTENCIA DE ERRO
243
+ erro_pop_up = await is_window_open("Erro")
244
+ if erro_pop_up["IsOpened"] == True:
245
+ error_work = await error_after_xml_imported()
246
+ return RpaRetornoProcessoDTO(
247
+ sucesso=error_work.sucesso,
248
+ retorno=error_work.retorno,
249
+ status=error_work.status,
250
+ tags=error_work.tags
251
+ )
252
+
253
+ app = Application().connect(
254
+ title="Informações para importação da Nota Fiscal Eletrônica"
255
+ )
256
+ main_window = app["Informações para importação da Nota Fiscal Eletrônica"]
257
+
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()
264
+
265
+ await worker_sleep(3)
266
+ # Mapeamento CFOP -> (lista, código exibido no combobox)
267
+ cfop_map = {
268
+ "1556": (['5101', '5102', '5103', '5104'], "1.556"),
269
+ "1407": (['5401', '5403', '5404', '5405'], "1.407"),
270
+ "2407": (['6104', '6401', '6403', '6405'], "2.407")
271
+ }
272
+
273
+ cfop_str = str(cfop)
274
+ for key, (lista, codigo_combo) in cfop_map.items():
275
+ if cfop_str in lista:
276
+ 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):
279
+ combo_box_natureza_operacao.select(opc)
280
+ send_keys("{ENTER}")
281
+ break
282
+ break
283
+
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
+ )
288
+ return RpaRetornoProcessoDTO(
289
+ sucesso=False,
290
+ retorno="Erro mapeado, CFOP diferente de início com 540 ou 510, necessário ação manual ou ajuste no robô.",
291
+ status=RpaHistoricoStatusEnum.Falha,
292
+ tags=[RpaTagDTO(descricao=RpaTagEnum.Negocio)]
293
+ )
294
+
295
+ await worker_sleep(3)
296
+
297
+ # INTERAGINDO COM O CAMPO ALMOXARIFADO
298
+ fornecedor = dados_nf[0]["fornecedorNome"]
299
+ empresaCodigo = dados_nf[0]["empresaCodigo"]
300
+ console.print(
301
+ f"Inserindo a informação do Almoxarifado {empresaCodigo} ...\n"
302
+ )
303
+ try:
304
+ new_app = Application(backend="uia").connect(
305
+ title="Informações para importação da Nota Fiscal Eletrônica"
306
+ )
307
+ 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
+ )
311
+ if empresa_codigo == '1':
312
+ valor_almoxarifado = empresaCodigo + "60"
313
+ else:
314
+ valor_almoxarifado = empresaCodigo + "50"
315
+ edit.set_edit_text(valor_almoxarifado)
316
+ edit.type_keys("{TAB}")
317
+ except Exception as e:
318
+ console.print(f"Erro ao iterar itens de almoxarifado: {e}")
319
+ return RpaRetornoProcessoDTO(
320
+ sucesso=False,
321
+ retorno=f"Erro ao iterar itens de almoxarifado: {e}",
322
+ status=RpaHistoricoStatusEnum.Falha,
323
+ tags=[RpaTagDTO(descricao=RpaTagEnum.Tecnico)]
324
+ )
325
+
326
+ await worker_sleep(1)
327
+ console.print("Inserir conta contábil")
328
+ despesa = nota.get('contaContabil')
329
+ despesa = despesa.split("-")[0].strip()
330
+ tipo_despesa_work = await tipo_despesa(despesa)
331
+ if tipo_despesa_work.sucesso == True:
332
+ console.log(tipo_despesa_work.retorno, style="bold green")
333
+ else:
334
+ return RpaRetornoProcessoDTO(
335
+ sucesso=False,
336
+ retorno=tipo_despesa_work.retorno,
337
+ status=RpaHistoricoStatusEnum.Falha,
338
+ tags=[RpaTagDTO(descricao=RpaTagEnum.Tecnico)]
339
+ )
340
+ await worker_sleep(5)
341
+
342
+ 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")
349
+ janela.set_focus()
350
+ # Clicar em canelar
351
+ janela.child_window(title="&Cancelar", class_name="TBitBtn").click()
352
+ console.print("Tipo de despesa não encontrado")
353
+ return RpaRetornoProcessoDTO(
354
+ sucesso=False,
355
+ retorno="Tipo de Despesa / conta contábil não localizado",
356
+ status=RpaHistoricoStatusEnum.Falha,
357
+ tags=[RpaTagDTO(descricao=RpaTagEnum.Negocio)]
358
+ )
359
+ except:
360
+ pass
361
+ # INTERAGINDO COM O CHECKBOX ZERAR ICMS
362
+ checkbox_zerar_icms = await zerar_icms()
363
+ if checkbox_zerar_icms.sucesso == True:
364
+ console.log(checkbox_zerar_icms.retorno, style="bold green")
365
+ else:
366
+ return RpaRetornoProcessoDTO(
367
+ sucesso=False,
368
+ retorno=checkbox_zerar_icms.retorno,
369
+ status=RpaHistoricoStatusEnum.Falha,
370
+ tags=[RpaTagDTO(descricao=RpaTagEnum.Tecnico)]
371
+ )
372
+
373
+ # INTERAGINDO COM O CAMPO DE CODIGO DO ICMS
374
+ if key =='1556':
375
+ codigo_icms = '33'
376
+ else:
377
+ codigo_icms = '20'
378
+ cod_icms_work = await cod_icms(codigo_icms)
379
+ if cod_icms_work.sucesso == True:
380
+ console.log(cod_icms_work.retorno, style="bold green")
381
+ else:
382
+ return RpaRetornoProcessoDTO(
383
+ sucesso=False,
384
+ retorno=cod_icms_work.retorno,
385
+ status=RpaHistoricoStatusEnum.Falha,
386
+ tags=[RpaTagDTO(descricao=RpaTagEnum.Tecnico)]
387
+ )
388
+
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
+ )
393
+ checkbox = window.child_window(
394
+ title="Manter Natureza de Operação selecionada",
395
+ class_name="TDBICheckBox",
396
+ )
397
+ if not checkbox.get_toggle_state() == 1:
398
+ checkbox.click()
399
+ console.print(
400
+ "A opção 'Manter Natureza de Operação selecionada' selecionado com sucesso... \n"
401
+ )
402
+
403
+ await worker_sleep(2)
404
+ console.print("Clicando em OK... \n")
405
+
406
+ max_attempts = 3
407
+ i = 0
408
+ while i < max_attempts:
409
+ console.print("Clicando no botão de OK...\n")
410
+ try:
411
+ try:
412
+ btn_ok = main_window.child_window(title="Ok")
413
+ btn_ok.click()
414
+ except:
415
+ btn_ok = main_window.child_window(title="&Ok")
416
+ btn_ok.click()
417
+ except:
418
+ console.print("Não foi possivel clicar no Botão OK... \n")
419
+
420
+ await worker_sleep(3)
421
+
422
+ console.print(
423
+ "Verificando a existencia da tela Informações para importação da Nota Fiscal Eletrônica...\n"
424
+ )
425
+
426
+ try:
427
+ informacao_nf_eletronica = await is_window_open(
428
+ "Informações para importação da Nota Fiscal Eletrônica"
429
+ )
430
+ 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
+ )
434
+ break
435
+ 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
+ )
439
+
440
+ i += 1
441
+
442
+ if i == max_attempts:
443
+ return RpaRetornoProcessoDTO(
444
+ 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",
446
+ status=RpaHistoricoStatusEnum.Falha,
447
+ tags=[RpaTagDTO(descricao=RpaTagEnum.Tecnico)]
448
+ )
449
+
450
+ await worker_sleep(10)
451
+
452
+ try:
453
+ console.print("Verificando itens não localizados ou NCM...\n")
454
+ itens_by_supplier = await is_window_open_by_class("TFrmAguarde", "TMessageForm")
455
+
456
+ if itens_by_supplier["IsOpened"] == True:
457
+ itens_by_supplier_work = await itens_not_found_supplier(nota.get("nfe"))
458
+
459
+ if not itens_by_supplier_work.sucesso:
460
+ return itens_by_supplier_work
461
+
462
+ except Exception as error:
463
+ return RpaRetornoProcessoDTO(
464
+ sucesso=False,
465
+ retorno=f"Falha ao verificar a existência de POP-UP de itens não localizados: {error}",
466
+ status=RpaHistoricoStatusEnum.Falha,
467
+ tags=[RpaTagDTO(descricao=RpaTagEnum.Tecnico)]
468
+ )
469
+
470
+ await worker_sleep(10)
471
+
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
476
+ while True:
477
+ local = pyautogui.locateCenterOnScreen(imagem, confidence=0.8) # 0.8 = 80% de precisão
478
+ if local:
479
+ pyautogui.click(local) # Clica no centro da imagem
480
+ print("Imagem encontrada e clicada!")
481
+ break
482
+ else:
483
+ print("Imagem não encontrada, tentando novamente...")
484
+ time.sleep(1)
485
+
486
+ await worker_sleep(3)
487
+ # Clicar em itens da nota
488
+ pyautogui.click(791, 379)
489
+ await worker_sleep(2)
490
+ index_item_atual = 0
491
+ index_ultimo_item = await get_ultimo_item()
492
+ console.print(f"Index ultimo item: {index_ultimo_item}")
493
+
494
+ try:
495
+ while index_item_atual < index_ultimo_item:
496
+ send_keys("^({HOME})")
497
+ await worker_sleep(1)
498
+
499
+ if index_item_atual > 0:
500
+ send_keys("{DOWN " + str(index_item_atual) + "}")
501
+
502
+ await worker_sleep(2)
503
+ send_keys("+{F10}")
504
+ await worker_sleep(1)
505
+ send_keys("{DOWN 2}")
506
+ await worker_sleep(1)
507
+ send_keys("{ENTER}")
508
+
509
+ await worker_sleep(2)
510
+ app = Application().connect(title="Alteração de Item")
511
+ main_window = app["Alteração de Item"]
512
+
513
+ main_window.set_focus()
514
+
515
+ edit = main_window.child_window(
516
+ class_name="TDBIEditCode", found_index=0
517
+ )
518
+ index_item_atual += 1
519
+ console.print(f"Item aual no final da execução: {index_item_atual}")
520
+ await worker_sleep(1)
521
+ # Listas
522
+ lista_icms_090 = ["5101", "5102", "5103", "5104"]
523
+ lista_icms_060 = ["5401", "5403", "5404", "5405", "6104", "6401", "6403", "6404", "6405"]
524
+
525
+ # Conecta à janela
526
+ app = Application().connect(class_name="TFrmAlteraItemNFE")
527
+ main_window = app["TFrmAlteraItemNFE"]
528
+ main_window.set_focus()
529
+
530
+
531
+ # Localiza o combobox
532
+
533
+ tipo_icms = main_window.child_window(class_name="TDBIComboBox", found_index=5)
534
+
535
+ # Define o texto da opção desejada
536
+ if cfop in lista_icms_090:
537
+ opcao_desejada = "090 - ICMS NACIONAL OUTRAS"
538
+ elif cfop in lista_icms_060:
539
+ opcao_desejada = "060 - ICMS - SUBSTITUICAO TRIBUTARIA 060"
540
+ else:
541
+ opcao_desejada = None
542
+
543
+ # Seleciona no combobox
544
+ if opcao_desejada:
545
+ try:
546
+ tipo_icms.select(opcao_desejada)
547
+ send_keys("{ENTER}")
548
+ except Exception as e:
549
+ print(f"Erro ao selecionar opção: {e}")
550
+
551
+ # Clicar em alterar
552
+ main_window.child_window(class_name="TDBIBitBtn", found_index=3).click()
553
+ await worker_sleep(5)
554
+ except Exception as e:
555
+ return {
556
+ "sucesso": False,
557
+ "retorno": f"Erro aotrabalhar nas alterações dos itens: {e}",
558
+ }
559
+
560
+ await worker_sleep(10)
561
+
562
+ console.print("Navegando pela Janela de Nota Fiscal de Entrada...\n")
563
+ app = Application().connect(class_name="TFrmNotaFiscalEntrada")
564
+ main_window = app["TFrmNotaFiscalEntrada"]
565
+
566
+ # Clicar em pagamentos
567
+ imagem = r"C:\Users\automatehub\Documents\GitHub\worker-automate-hub\worker_automate_hub\assets\entrada_notas\pagamentos.png"
568
+
569
+ # Tenta localizar a imagem na tela
570
+ while True:
571
+ local = pyautogui.locateCenterOnScreen(imagem, confidence=0.8) # 0.8 = 80% de precisão
572
+ if local:
573
+ pyautogui.click(local) # Clica no centro da imagem
574
+ print("Imagem encontrada e clicada!")
575
+ break
576
+ else:
577
+ print("Imagem não encontrada, tentando novamente...")
578
+ time.sleep(1)
579
+
580
+ await worker_sleep(3)
581
+
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
592
+ opcoes = [
593
+ "BANCO DO BRASIL BOLETO FIDC",
594
+ "BANCO DO BRASIL BOLETO",
595
+ "BOLETO"
596
+ ]
597
+
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}")
604
+ 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
+
612
+ # Converte para date (formato yyyy-mm-dd → ISO)
613
+ data_vencimento = datetime.strptime(dt_vencimento_nota, "%Y-%m-%d").date()
614
+
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)
618
+
619
+ # Ajusta para cair só em dias úteis
620
+ while data_vencimento.weekday() >= 5: # 5 = sábado, 6 = domingo
621
+ data_vencimento += timedelta(days=1)
622
+
623
+ # Converter para string (formato brasileiro dd/mm/yyyy)
624
+ 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
+ )
631
+
632
+ data_venc.set_edit_text(data_vencimento_str)
633
+
634
+ console.print(f"Incluindo registro...\n")
635
+ 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
+ )
640
+ pyautogui.click(inserir_registro)
641
+ except Exception as e:
642
+ console.print(
643
+ f"Não foi possivel incluir o registro utilizando reconhecimento de imagem, Error: {e}...\n tentando inserir via posição...\n"
644
+ )
645
+ await incluir_registro()
646
+
647
+ 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
+
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"]
666
+
667
+ 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
697
+
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
705
+
706
+ if not aguarde_rateio_despesa:
707
+ break
708
+
709
+ i += 1
710
+
711
+ if aguarde_rateio_despesa:
712
+ return RpaRetornoProcessoDTO(
713
+ sucesso=False,
714
+ retorno=f"Número máximo de tentativas atingido. A tela para Rateio da Despesa não foi encontrada.",
715
+ status=RpaHistoricoStatusEnum.Falha,
716
+ tags=[RpaTagDTO(descricao=RpaTagEnum.Tecnico)]
717
+ )
718
+
719
+ despesa_rateio_work = await rateio_despesa(empresaCodigo)
720
+ if despesa_rateio_work.sucesso == True:
721
+ console.log(despesa_rateio_work.retorno, style="bold green")
722
+ else:
723
+ return RpaRetornoProcessoDTO(
724
+ sucesso=False,
725
+ retorno=despesa_rateio_work.retorno,
726
+ status=RpaHistoricoStatusEnum.Falha,
727
+ tags=despesa_rateio_work.tags
728
+ )
729
+
730
+ # Verifica se a info 'Nota fiscal incluida' está na tela
731
+ await worker_sleep(15)
732
+ 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")
740
+
741
+ window_rect = main_window.rectangle()
742
+ screenshot = pyautogui.screenshot(
743
+ region=(
744
+ window_rect.left,
745
+ window_rect.top,
746
+ window_rect.width(),
747
+ window_rect.height(),
748
+ )
749
+ )
750
+ username = getpass.getuser()
751
+ path_to_png = f"C:\\Users\\{username}\\Downloads\\warning_popup_{nota.get("nfe")}.png"
752
+ screenshot.save(path_to_png)
753
+ console.print(f"Print salvo em {path_to_png}...\n")
754
+
755
+ console.print(
756
+ f"Preparando a imagem para maior resolução e assertividade no OCR...\n"
757
+ )
758
+ image = Image.open(path_to_png)
759
+ image = image.convert("L")
760
+ enhancer = ImageEnhance.Contrast(image)
761
+ image = enhancer.enhance(2.0)
762
+ image.save(path_to_png)
763
+ console.print(f"Imagem preparada com sucesso...\n")
764
+ console.print(f"Realizando OCR...\n")
765
+ captured_text = pytesseract.image_to_string(Image.open(path_to_png))
766
+ console.print(
767
+ f"Texto Full capturado {captured_text}...\n"
768
+ )
769
+ os.remove(path_to_png)
770
+ if 'movimento não permitido' in captured_text.lower():
771
+ 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)]
776
+ )
777
+ else:
778
+ 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)]
783
+ )
784
+
785
+ await worker_sleep(3)
786
+ # Verifica se a nota foi lançada
787
+ nf_imported = await check_nota_importada(dados_nf[0].get("chaveNfe"))
788
+ if nf_imported.sucesso == True:
789
+ 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)
793
+ if status_nf_emsys.get("status") == "Lançada":
794
+ console.print("\nNota lançada com sucesso, processo finalizado...", style="bold green")
795
+ return RpaRetornoProcessoDTO(
796
+ sucesso=True,
797
+ retorno="Nota Lançada com sucesso!",
798
+ status=RpaHistoricoStatusEnum.Sucesso,
799
+ )
800
+ else:
801
+ console.print("Erro ao lançar nota", style="bold red")
802
+ return RpaRetornoProcessoDTO(
803
+ 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}",
805
+ status=RpaHistoricoStatusEnum.Falha,
806
+ tags=[RpaTagDTO(descricao=RpaTagEnum.Negocio)]
807
+ )
808
+ else:
809
+ console.print("Erro ao lançar nota", style="bold red")
810
+ return RpaRetornoProcessoDTO(
811
+ sucesso=False,
812
+ retorno=f"Erro ao lançar nota, erro: {nf_imported.retorno}",
813
+ status=RpaHistoricoStatusEnum.Falha,
814
+ tags=[RpaTagDTO(descricao=RpaTagEnum.Tecnico)]
815
+ )
816
+
817
+ except Exception as ex:
818
+ observacao = f"Erro Processo Entrada de Notas: {str(ex)}"
819
+ logger.error(observacao)
820
+ console.print(observacao, style="bold red")
821
+ return RpaRetornoProcessoDTO(
822
+ sucesso=False,
823
+ retorno=observacao,
824
+ status=RpaHistoricoStatusEnum.Falha,
825
+ tags=[RpaTagDTO(descricao=RpaTagEnum.Tecnico)]
826
+ )
827
+
828
+ finally:
829
+ # Deleta o xml
830
+ await delete_xml(numero_nota)
831
+
832
+
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: worker-automate-hub
3
- Version: 0.5.737
3
+ Version: 0.5.738
4
4
  Summary: Worker Automate HUB é uma aplicação para automatizar rotinas de RPA nos ambientes Argenta.
5
5
  Author: Joel Paim
6
6
  Requires-Python: >=3.12,<4.0
@@ -1,7 +1,7 @@
1
1
  worker_automate_hub/__init__.py,sha256=LV28uQvBfpPIqudGIMJmVB8E941MjXHcu8DMoX5n8AM,25
2
2
  worker_automate_hub/api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
3
  worker_automate_hub/api/ahead_service.py,sha256=QbNrZf9q7fS0s-S5fZVytqC7dINi9u2f6aB6SDrGVVA,2231
4
- worker_automate_hub/api/client.py,sha256=evBsq_CURD_tWgZC1XqTLxWPerPSuEpS89KHD4i2VJA,25787
4
+ worker_automate_hub/api/client.py,sha256=dKHMJEwBPo5_r-9487APuZmnVjKh3WaiwpNZIN0j2vs,31763
5
5
  worker_automate_hub/api/datalake_service.py,sha256=qw_N_OOgDKDuPbI-fdYkWWTlT4CUtFTl0VVlZ0fLM-M,3001
6
6
  worker_automate_hub/api/helpers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
7
  worker_automate_hub/api/helpers/api_helpers.py,sha256=SkheO2fXexeh-a4shr8Qzsz_kZhuSG0DJ7kbODctRbM,3696
@@ -84,6 +84,7 @@ worker_automate_hub/tasks/jobs/lancamento_rateio.py,sha256=0cvbpuJiHl5mca5gpZudX
84
84
  worker_automate_hub/tasks/jobs/login_emsys.py,sha256=dO9S027qRTtjOfytF6IWO-m6hDld8kZqOVAsn91l1YA,5684
85
85
  worker_automate_hub/tasks/jobs/login_emsys_versao_especifica.py,sha256=_6CFh79eaW9KdPGR6FMV01ASPjJzNzzBK1MvC_uiSOo,5625
86
86
  worker_automate_hub/tasks/jobs/notas_faturamento_sap.py,sha256=p6tVE027FHHXBxt2sIDxqLInpf_0wS-8TcACnS34p7w,13961
87
+ worker_automate_hub/tasks/jobs/opex_capex.py,sha256=8iOhWY0BUXugitJa-a0jtsPh656LFuptwfiZV9yU8G0,33246
87
88
  worker_automate_hub/tasks/jobs/playground.py,sha256=7vWDg9DwToHwGJ6_XOa8TQ6LmfRV5Qz2TaOV3q3P9sA,1918
88
89
  worker_automate_hub/tasks/jobs/sped_fiscal.py,sha256=Zsq-IwKxA0b2tikO6Rri4WXVj10jK-Jd0-gxk8yVBH0,31064
89
90
  worker_automate_hub/tasks/jobs/transferencias.py,sha256=X-hbz0GSsdeUHOZlz_wZ1XvNfWiQI0Ms2bD7VP-mcbE,45539
@@ -98,7 +99,7 @@ worker_automate_hub/utils/updater.py,sha256=en2FCGhI8aZ-JNP3LQm64NJDc4awCNW7UhbV
98
99
  worker_automate_hub/utils/util.py,sha256=nV09AF8lu5poiMzWMAAgVS_VWvEuIRfNDmx46V7Nvzk,207279
99
100
  worker_automate_hub/utils/utils_nfe_entrada.py,sha256=qS_REFGudeZhoOkamUst8WzW1XyMGws5GehrMr5XZTM,38085
100
101
  worker_automate_hub/worker.py,sha256=TKTEm6vAf5p_Y_GwvIac7KRUQjlfdHTrkR73NbkjOvk,7190
101
- worker_automate_hub-0.5.737.dist-info/entry_points.txt,sha256=sddyhjx57I08RY8X7UxcTpdoOsWULAWNKN9Xr6pp_Kw,54
102
- worker_automate_hub-0.5.737.dist-info/METADATA,sha256=1ONXyoX9tDwXnURu7jGk9jsc8tVkZlQhln4Tt46N474,3049
103
- worker_automate_hub-0.5.737.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
104
- worker_automate_hub-0.5.737.dist-info/RECORD,,
102
+ worker_automate_hub-0.5.738.dist-info/entry_points.txt,sha256=sddyhjx57I08RY8X7UxcTpdoOsWULAWNKN9Xr6pp_Kw,54
103
+ worker_automate_hub-0.5.738.dist-info/METADATA,sha256=68VnfamLXGURb8yHdOSQTpsJlylzm6AfCdtJqaW2YSU,3049
104
+ worker_automate_hub-0.5.738.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
105
+ worker_automate_hub-0.5.738.dist-info/RECORD,,