worker-automate-hub 0.5.828__py3-none-any.whl → 0.5.829__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.
- worker_automate_hub/api/client.py +86 -2
- worker_automate_hub/tasks/jobs/devolucao_produtos.py +991 -0
- worker_automate_hub/tasks/task_definitions.py +8 -2
- worker_automate_hub/utils/util.py +17 -4
- {worker_automate_hub-0.5.828.dist-info → worker_automate_hub-0.5.829.dist-info}/METADATA +1 -1
- {worker_automate_hub-0.5.828.dist-info → worker_automate_hub-0.5.829.dist-info}/RECORD +8 -7
- {worker_automate_hub-0.5.828.dist-info → worker_automate_hub-0.5.829.dist-info}/WHEEL +0 -0
- {worker_automate_hub-0.5.828.dist-info → worker_automate_hub-0.5.829.dist-info}/entry_points.txt +0 -0
|
@@ -2,12 +2,13 @@ from decimal import ROUND_HALF_UP, Decimal
|
|
|
2
2
|
import threading
|
|
3
3
|
from typing import Optional
|
|
4
4
|
import aiohttp
|
|
5
|
-
|
|
5
|
+
import re
|
|
6
|
+
from collections import defaultdict
|
|
6
7
|
import aiohttp
|
|
7
8
|
import requests
|
|
8
9
|
from aiohttp import ClientSession
|
|
9
10
|
from rich.console import Console
|
|
10
|
-
|
|
11
|
+
from typing import List, Dict, Any
|
|
11
12
|
from worker_automate_hub.api.helpers.api_helpers import handle_api_response
|
|
12
13
|
from worker_automate_hub.config.settings import load_env_config
|
|
13
14
|
from worker_automate_hub.models.dao.rpa_configuracao import RpaConfiguracao
|
|
@@ -498,6 +499,89 @@ async def get_valor_remessa_cobranca(date: str):
|
|
|
498
499
|
logger.info(err_msg)
|
|
499
500
|
|
|
500
501
|
|
|
502
|
+
async def get_notas_produtos(codFornecedor: int, codEmpresa: int, itens: List[Dict[str, Any]]) -> Dict[str, Any]:
|
|
503
|
+
"""
|
|
504
|
+
Função única:
|
|
505
|
+
- Converte itens (aceita chaves codigo/codigoProduto e quantidade/qtd)
|
|
506
|
+
- Chama /nf-supplier/checker com Authorization: Basic
|
|
507
|
+
- Normaliza tipos do retorno
|
|
508
|
+
- Entrega:
|
|
509
|
+
{
|
|
510
|
+
"lista": [ {codItem, qtdTotal, notas, valorUnitario}, ... ],
|
|
511
|
+
"por_codigo": { codItem: {...}, ... }
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
Retorno esperado da API (ex):
|
|
515
|
+
[
|
|
516
|
+
{"codItem": 19969, "qtdTotal": 15, "notas": ["1418727","1410744"], "valorUnitario": 5.29},
|
|
517
|
+
{"codItem": 29272, "qtdTotal": 10, "notas": ["1418727"], "valorUnitario": 7.12}
|
|
518
|
+
]
|
|
519
|
+
"""
|
|
520
|
+
# --- Carrega config
|
|
521
|
+
env_config, _ = load_env_config()
|
|
522
|
+
url_base = env_config["API_BASE_URL"].rstrip("/")
|
|
523
|
+
url = f"{url_base}/nf-supplier/checker"
|
|
524
|
+
|
|
525
|
+
# --- Header Basic (aceita token puro ou já "Basic ...")
|
|
526
|
+
token = (env_config.get("API_AUTHORIZATION") or "").strip()
|
|
527
|
+
auth_header = token if token.lower().startswith("basic ") else f"Basic {token}"
|
|
528
|
+
|
|
529
|
+
# --- Converte itens de entrada
|
|
530
|
+
itens_convertidos: List[Dict[str, int]] = []
|
|
531
|
+
for it in itens or []:
|
|
532
|
+
codigo = re.findall(r"\d+", it.get("descricaoProduto"))[0]
|
|
533
|
+
quantidade = it.get("quantidade", it.get("qtd"))
|
|
534
|
+
if codigo is None or quantidade is None:
|
|
535
|
+
logger.warning(f"Item incompleto: {it}")
|
|
536
|
+
console.print(f"⚠️ Item incompleto: {it}", style="yellow")
|
|
537
|
+
continue
|
|
538
|
+
try:
|
|
539
|
+
itens_convertidos.append({"codigo": int(codigo), "quantidade": int(quantidade)})
|
|
540
|
+
except Exception:
|
|
541
|
+
logger.warning(f"Item inválido (não numérico): {it}")
|
|
542
|
+
console.print(f"⚠️ Item inválido (não numérico): {it}", style="yellow")
|
|
543
|
+
|
|
544
|
+
body = {
|
|
545
|
+
"codFornecedor": int(codFornecedor),
|
|
546
|
+
"codEmpresa": int(codEmpresa),
|
|
547
|
+
"itens": itens_convertidos,
|
|
548
|
+
}
|
|
549
|
+
headers = {"Authorization": auth_header, "Content-Type": "application/json"}
|
|
550
|
+
|
|
551
|
+
# --- Chamada HTTP
|
|
552
|
+
async with aiohttp.ClientSession(connector=aiohttp.TCPConnector(verify_ssl=False)) as session:
|
|
553
|
+
async with session.post(url, json=body, headers=headers) as resp:
|
|
554
|
+
text = await resp.text()
|
|
555
|
+
if resp.status != 200:
|
|
556
|
+
raise RuntimeError(f"HTTP {resp.status} ao chamar {url}: {text}")
|
|
557
|
+
try:
|
|
558
|
+
data = await resp.json()
|
|
559
|
+
except Exception:
|
|
560
|
+
raise RuntimeError(f"Resposta não-JSON do servidor: {text[:600]}")
|
|
561
|
+
|
|
562
|
+
console.print(f"✅ Resposta da API: {data}", style="bold green")
|
|
563
|
+
logger.info(f"nf-supplier/checker -> {data}")
|
|
564
|
+
|
|
565
|
+
if not isinstance(data, list):
|
|
566
|
+
raise ValueError(f"Formato inesperado da API: {type(data)} -> {data}")
|
|
567
|
+
|
|
568
|
+
# --- Normaliza tipos e monta índices
|
|
569
|
+
lista_norm: List[Dict[str, Any]] = []
|
|
570
|
+
por_codigo: Dict[int, Dict[str, Any]] = {}
|
|
571
|
+
|
|
572
|
+
for row in data:
|
|
573
|
+
cod = int(row.get("codItem"))
|
|
574
|
+
item_norm = {
|
|
575
|
+
"codItem": cod,
|
|
576
|
+
"qtdTotal": int(row.get("qtdTotal", 0)),
|
|
577
|
+
"notas": [str(n) for n in (row.get("notas") or [])],
|
|
578
|
+
"valorUnitario": float(row.get("valorUnitario", 0.0)),
|
|
579
|
+
}
|
|
580
|
+
lista_norm.append(item_norm)
|
|
581
|
+
por_codigo[cod] = item_norm
|
|
582
|
+
|
|
583
|
+
return {"lista": lista_norm, "por_codigo": por_codigo}
|
|
584
|
+
|
|
501
585
|
async def get_status_nf_emsys(chave: int):
|
|
502
586
|
"""
|
|
503
587
|
Procura o status de nota fiscal no EMSYS.
|
|
@@ -0,0 +1,991 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
import warnings
|
|
3
|
+
from datetime import datetime
|
|
4
|
+
import json
|
|
5
|
+
import io
|
|
6
|
+
import pyautogui
|
|
7
|
+
from pywinauto.application import Application
|
|
8
|
+
from pywinauto import keyboard
|
|
9
|
+
from pywinauto import Desktop
|
|
10
|
+
from collections import defaultdict
|
|
11
|
+
from rich.console import Console
|
|
12
|
+
import getpass
|
|
13
|
+
import time
|
|
14
|
+
import re
|
|
15
|
+
import sys
|
|
16
|
+
import os
|
|
17
|
+
|
|
18
|
+
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', '..')))
|
|
19
|
+
|
|
20
|
+
from worker_automate_hub.api.client import get_config_by_name, send_file, get_notas_produtos
|
|
21
|
+
from worker_automate_hub.models.dto.rpa_historico_request_dto import (
|
|
22
|
+
RpaHistoricoStatusEnum,
|
|
23
|
+
RpaRetornoProcessoDTO,
|
|
24
|
+
RpaTagDTO,
|
|
25
|
+
RpaTagEnum,
|
|
26
|
+
)
|
|
27
|
+
from worker_automate_hub.models.dto.rpa_processo_entrada_dto import (
|
|
28
|
+
RpaProcessoEntradaDTO,
|
|
29
|
+
)
|
|
30
|
+
from worker_automate_hub.utils.logger import logger
|
|
31
|
+
from pywinauto.keyboard import send_keys
|
|
32
|
+
# from worker_automate_hub.utils.toast import show_toast
|
|
33
|
+
from worker_automate_hub.utils.util import (
|
|
34
|
+
send_to_webhook,
|
|
35
|
+
extract_nf_number, # permanece importado, mesmo sem uso
|
|
36
|
+
faturar_pre_venda,
|
|
37
|
+
find_element_center,
|
|
38
|
+
find_target_position,
|
|
39
|
+
kill_all_emsys,
|
|
40
|
+
login_emsys,
|
|
41
|
+
set_variable,
|
|
42
|
+
take_screenshot,
|
|
43
|
+
take_target_position,
|
|
44
|
+
type_text_into_field,
|
|
45
|
+
wait_nf_ready,
|
|
46
|
+
wait_window_close,
|
|
47
|
+
worker_sleep,
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
console = Console()
|
|
51
|
+
|
|
52
|
+
ASSETS_BASE_PATH = "assets/descartes_transferencias_images/"
|
|
53
|
+
ALMOXARIFADO_DEFAULT = "50"
|
|
54
|
+
|
|
55
|
+
def _parse_int_tolerante(val):
|
|
56
|
+
if val is None:
|
|
57
|
+
return 0
|
|
58
|
+
if isinstance(val, int):
|
|
59
|
+
return val
|
|
60
|
+
s = str(val).replace("\u00a0", "").strip() # remove NBSP
|
|
61
|
+
s = s.replace(".", "").replace(",", "") # remove separadores comuns
|
|
62
|
+
return int(float(s or 0))
|
|
63
|
+
|
|
64
|
+
def _coletar_itens_achatados(d: dict):
|
|
65
|
+
descrs, qtds = {}, {}
|
|
66
|
+
for k, v in d.items():
|
|
67
|
+
m = re.match(r"^descricaoProduto(\d+)$", k, flags=re.I)
|
|
68
|
+
if m:
|
|
69
|
+
descrs[m.group(1)] = v
|
|
70
|
+
continue
|
|
71
|
+
m = re.match(r"^qtd(\d+)$", k, flags=re.I)
|
|
72
|
+
if m:
|
|
73
|
+
qtds[m.group(1)] = v
|
|
74
|
+
continue
|
|
75
|
+
|
|
76
|
+
itens = []
|
|
77
|
+
idxs = sorted(set(descrs.keys()) | set(qtds.keys()), key=lambda x: int(x))
|
|
78
|
+
for n in idxs:
|
|
79
|
+
desc = (descrs.get(n) or "").strip()
|
|
80
|
+
if not desc:
|
|
81
|
+
continue
|
|
82
|
+
qtd = _parse_int_tolerante(qtds.get(n, 0))
|
|
83
|
+
if qtd <= 0:
|
|
84
|
+
continue
|
|
85
|
+
itens.append({"descricaoProduto": desc, "qtd": qtd})
|
|
86
|
+
return itens
|
|
87
|
+
|
|
88
|
+
def normalize_config_entrada(cfg: dict) -> dict:
|
|
89
|
+
"""
|
|
90
|
+
Se vier com 'itens': mantém e normaliza qtd -> int.
|
|
91
|
+
Se vier como descricaoProdutoN/qtdN: converte para 'itens'.
|
|
92
|
+
Preserva demais campos.
|
|
93
|
+
"""
|
|
94
|
+
cfg = dict(cfg or {})
|
|
95
|
+
if isinstance(cfg.get("itens"), list):
|
|
96
|
+
itens_norm = []
|
|
97
|
+
for it in cfg["itens"]:
|
|
98
|
+
if not isinstance(it, dict):
|
|
99
|
+
continue
|
|
100
|
+
desc = str(it.get("descricaoProduto", "")).strip()
|
|
101
|
+
if not desc:
|
|
102
|
+
continue
|
|
103
|
+
qtd = _parse_int_tolerante(it.get("qtd", it.get("quantidade", 0)))
|
|
104
|
+
if qtd <= 0:
|
|
105
|
+
continue
|
|
106
|
+
itens_norm.append({"descricaoProduto": desc, "qtd": qtd})
|
|
107
|
+
cfg["itens"] = itens_norm
|
|
108
|
+
return cfg
|
|
109
|
+
|
|
110
|
+
# formato achatado
|
|
111
|
+
itens = _coletar_itens_achatados(cfg)
|
|
112
|
+
cfg["itens"] = itens
|
|
113
|
+
# remove chaves achatadas da saída (opcional)
|
|
114
|
+
chaves_remover = [k for k in cfg.keys() if re.match(r"^(descricaoProduto|qtd)\d+$", k, flags=re.I)]
|
|
115
|
+
for k in chaves_remover:
|
|
116
|
+
cfg.pop(k, None)
|
|
117
|
+
return cfg
|
|
118
|
+
# --- fim do normalizador ---
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
async def devolucao_produtos(task: RpaProcessoEntradaDTO) -> RpaRetornoProcessoDTO:
|
|
122
|
+
try:
|
|
123
|
+
# Get config from BOF
|
|
124
|
+
config = await get_config_by_name("login_emsys")
|
|
125
|
+
console.print(task)
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
# Seta config entrada na var nota para melhor entendimento (normalizando formatos)
|
|
129
|
+
nota = normalize_config_entrada(task.configEntrada)
|
|
130
|
+
itens = nota.get("itens", [])
|
|
131
|
+
|
|
132
|
+
descricao_filial = task.configEntrada.get("descricaoFilial", "")
|
|
133
|
+
empresa = descricao_filial.split(" - ")[0]
|
|
134
|
+
estado = nota.get("estado", "")
|
|
135
|
+
descricao_fornecedor = nota.get("descricaoFornecedor", "")
|
|
136
|
+
historico_id = task.historico_id
|
|
137
|
+
cod_fornecedor = descricao_fornecedor.split(" - ")[0]
|
|
138
|
+
identificador = nota.get("identificador", "")
|
|
139
|
+
url_retorno = nota.get("urlRetorno", "")
|
|
140
|
+
multiplicador_timeout = int(float(task.sistemas[0].timeout))
|
|
141
|
+
set_variable("timeout_multiplicador", multiplicador_timeout)
|
|
142
|
+
|
|
143
|
+
# ========= CHAMADA AO ENDPOINT E MONTAGEM DO DATA =========
|
|
144
|
+
# res deve retornar {"lista": [...], "por_codigo": {cod: {...}}}
|
|
145
|
+
res = await get_notas_produtos(int(cod_fornecedor), int(empresa), itens)
|
|
146
|
+
by_code = res.get("por_codigo", {}) or {} # dict dinâmico por código
|
|
147
|
+
|
|
148
|
+
# Constrói os itens na estrutura usada no fluxo de UI
|
|
149
|
+
itens_ui = []
|
|
150
|
+
notas_encontradas = [] # acumula notas para deduplicar depois
|
|
151
|
+
|
|
152
|
+
for it in itens:
|
|
153
|
+
# aceita "codigoProduto"/"quantidade" e "codigo"/"qtd"
|
|
154
|
+
desc = it.get("descricaoProduto", "") or ""
|
|
155
|
+
nums = re.findall(r"\d+", desc)
|
|
156
|
+
if not nums:
|
|
157
|
+
# fallback: tenta campo "codigo" direto (se existir)
|
|
158
|
+
cod_raw = it.get("codigo") or it.get("codigoProduto")
|
|
159
|
+
if cod_raw is None:
|
|
160
|
+
continue
|
|
161
|
+
try:
|
|
162
|
+
cod = int(re.findall(r"\d+", str(cod_raw))[0])
|
|
163
|
+
except Exception:
|
|
164
|
+
continue
|
|
165
|
+
else:
|
|
166
|
+
cod = int(nums[0])
|
|
167
|
+
|
|
168
|
+
# quantidade (como int)
|
|
169
|
+
qtd_raw = it.get("quantidade", it.get("qtd"))
|
|
170
|
+
try:
|
|
171
|
+
qtd = int(qtd_raw)
|
|
172
|
+
if qtd <= 0:
|
|
173
|
+
continue
|
|
174
|
+
except (TypeError, ValueError):
|
|
175
|
+
continue
|
|
176
|
+
|
|
177
|
+
info = by_code.get(cod) or {}
|
|
178
|
+
valor_unit = float(info.get("valorUnitario", 0) or 0)
|
|
179
|
+
|
|
180
|
+
# Normaliza "notas" para lista de strings
|
|
181
|
+
notas_item = info.get("notas") or []
|
|
182
|
+
if isinstance(notas_item, (str, int)):
|
|
183
|
+
notas_item = [notas_item]
|
|
184
|
+
notas_item = [str(n) for n in notas_item]
|
|
185
|
+
|
|
186
|
+
# Acumula para a lista geral (será deduplicada depois)
|
|
187
|
+
notas_encontradas.extend(notas_item)
|
|
188
|
+
|
|
189
|
+
itens_ui.append({
|
|
190
|
+
"codigo": cod,
|
|
191
|
+
"quantidade": qtd,
|
|
192
|
+
"valor_unitario": valor_unit,
|
|
193
|
+
"valor_total_item": round(valor_unit * qtd, 2),
|
|
194
|
+
"notas": notas_item, # mantém vínculo item↔notas
|
|
195
|
+
})
|
|
196
|
+
|
|
197
|
+
# Deduplica notas preservando a ordem de aparição
|
|
198
|
+
nf_ref = list(dict.fromkeys(notas_encontradas))
|
|
199
|
+
|
|
200
|
+
# Índice opcional: itens por cada nota (facilita inclusão na UI)
|
|
201
|
+
itens_por_nota = defaultdict(list)
|
|
202
|
+
for item in itens_ui:
|
|
203
|
+
for n in item["notas"]:
|
|
204
|
+
itens_por_nota[n].append(item)
|
|
205
|
+
|
|
206
|
+
data = {
|
|
207
|
+
"nf_referencia": nf_ref, # ex.: ['1418727', '1410744']
|
|
208
|
+
"itens": itens_ui, # cada item com suas notas
|
|
209
|
+
"totais": {
|
|
210
|
+
"valor_final": round(sum(i["valor_total_item"] for i in itens_ui), 2)
|
|
211
|
+
},
|
|
212
|
+
"itens_por_nota": itens_por_nota # para uso direto no fluxo de UI
|
|
213
|
+
}
|
|
214
|
+
# ========= FIM DA MONTAGEM DO DATA =========
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
# Fecha a instancia do emsys - caso esteja aberta
|
|
218
|
+
await kill_all_emsys()
|
|
219
|
+
|
|
220
|
+
app = Application(backend="win32").start("C:\\Rezende\\EMSys3\\EMSys3.exe")
|
|
221
|
+
warnings.filterwarnings(
|
|
222
|
+
"ignore",
|
|
223
|
+
category=UserWarning,
|
|
224
|
+
message="32-bit application should be automated using 32-bit Python",
|
|
225
|
+
)
|
|
226
|
+
console.print("\nEMSys iniciando...", style="bold green")
|
|
227
|
+
return_login = await login_emsys(config.conConfiguracao, app, task)
|
|
228
|
+
|
|
229
|
+
if return_login.sucesso == True:
|
|
230
|
+
console.print("Pesquisando por: Cadastro Pré Venda")
|
|
231
|
+
type_text_into_field(
|
|
232
|
+
"Cadastro Pre-Venda", app["TFrmMenuPrincipal"]["Edit"], True, "50"
|
|
233
|
+
)
|
|
234
|
+
pyautogui.press("enter")
|
|
235
|
+
await worker_sleep(1)
|
|
236
|
+
pyautogui.press("enter")
|
|
237
|
+
console.print(
|
|
238
|
+
f"\nPesquisa: 'Cadastro Pre Venda' realizada com sucesso",
|
|
239
|
+
style="bold green",
|
|
240
|
+
)
|
|
241
|
+
await worker_sleep(3)
|
|
242
|
+
try:
|
|
243
|
+
app = Application().connect(class_name="TFrmSelecionaTipoPreVenda")
|
|
244
|
+
select_prevenda_type = app["Selecione o Tipo de Pré-Venda"]
|
|
245
|
+
|
|
246
|
+
if select_prevenda_type.exists():
|
|
247
|
+
tipo = select_prevenda_type.child_window(class_name="TComboBox", found_index=0)
|
|
248
|
+
tipo.select("Orçamento")
|
|
249
|
+
confirm = select_prevenda_type.child_window(class_name="TDBIBitBtn", found_index=1)
|
|
250
|
+
confirm.click()
|
|
251
|
+
except:
|
|
252
|
+
console.print("Sem tela de selecionar modelo de pre venda", style="bold green")
|
|
253
|
+
else:
|
|
254
|
+
logger.info(f"\nError Message: {return_login.retorno}")
|
|
255
|
+
console.print(f"\nError Message: {return_login.retorno}", style="bold red")
|
|
256
|
+
return return_login
|
|
257
|
+
|
|
258
|
+
await worker_sleep(7)
|
|
259
|
+
|
|
260
|
+
# Condição da Pré-Venda
|
|
261
|
+
console.print("Selecionando a Condição da Pré-Venda\n")
|
|
262
|
+
app = Application().connect(class_name="TFrmPreVenda")
|
|
263
|
+
main_window = app["TFrmPreVenda"]
|
|
264
|
+
|
|
265
|
+
condicao_field = main_window.child_window(class_name="TDBIComboBox", found_index=2)
|
|
266
|
+
condicao_field.select("21 DIAS")
|
|
267
|
+
|
|
268
|
+
# Código do fornecedor
|
|
269
|
+
input_cod_fornecedor = main_window.child_window(class_name="TDBIEditNumber", found_index=2)
|
|
270
|
+
input_cod_fornecedor.click_input()
|
|
271
|
+
await worker_sleep(0.2)
|
|
272
|
+
keyboard.send_keys("{END}+{HOME}{DEL}")
|
|
273
|
+
await worker_sleep(0.2)
|
|
274
|
+
input_cod_fornecedor.type_keys(str(cod_fornecedor), with_spaces=True, set_foreground=True)
|
|
275
|
+
keyboard.send_keys("{TAB}")
|
|
276
|
+
await worker_sleep(5)
|
|
277
|
+
|
|
278
|
+
# Popups
|
|
279
|
+
try:
|
|
280
|
+
app = Application().connect(class_name="TFrmSelecionaEndereco")
|
|
281
|
+
app["TFrmSelecionaEndereco"].close()
|
|
282
|
+
await worker_sleep(3)
|
|
283
|
+
app = Application().connect(class_name="TMessageForm")
|
|
284
|
+
app["TMessageForm"].child_window(class_name="TButton", found_index=0).click()
|
|
285
|
+
except:
|
|
286
|
+
pass
|
|
287
|
+
|
|
288
|
+
app = Application().connect(class_name="TFrmPreVenda")
|
|
289
|
+
main_window = app["TFrmPreVenda"]
|
|
290
|
+
console.print("Verificar estado...")
|
|
291
|
+
if estado != "RS":
|
|
292
|
+
modelo = "DEVOLUÇÃO DE COMPRA DE MERCADORIAS SC"
|
|
293
|
+
else:
|
|
294
|
+
modelo = "DEVOLUCAO DE COMPRA DE MERCADORIAS - TRIBUTADO"
|
|
295
|
+
|
|
296
|
+
# Inserir modelo
|
|
297
|
+
console.print("Inserir modelo...")
|
|
298
|
+
select_modelo = main_window.child_window(class_name="TDBIComboBox", found_index=0)
|
|
299
|
+
select_modelo.select(modelo)
|
|
300
|
+
await worker_sleep(1)
|
|
301
|
+
|
|
302
|
+
# Abrir guia de itens (por imagem)
|
|
303
|
+
imagem_item = r"C:\Users\automatehub\Desktop\img_leo\itens.png"
|
|
304
|
+
for _ in range(10):
|
|
305
|
+
pos = pyautogui.locateCenterOnScreen(imagem_item, confidence=0.9)
|
|
306
|
+
if pos:
|
|
307
|
+
pyautogui.click(pos)
|
|
308
|
+
break
|
|
309
|
+
await worker_sleep(1)
|
|
310
|
+
else:
|
|
311
|
+
print("Imagem do item não encontrada na tela.")
|
|
312
|
+
await worker_sleep(2)
|
|
313
|
+
|
|
314
|
+
# Incluir item
|
|
315
|
+
botao_incluir = main_window.child_window(title="Incluir", class_name="TDBIBitBtn").wrapper_object()
|
|
316
|
+
botao_incluir.click_input()
|
|
317
|
+
await worker_sleep(5)
|
|
318
|
+
|
|
319
|
+
# =============== PREPARO DE DADOS ===============
|
|
320
|
+
almoxarifado = f"{descricao_filial}50"
|
|
321
|
+
|
|
322
|
+
# =============== ALMOXARIFADO ===============
|
|
323
|
+
console.print("Inserir Almoxarifado...")
|
|
324
|
+
# Abre tela de inclusão de item
|
|
325
|
+
app_item = Application().connect(class_name="TFrmIncluiItemPreVenda")
|
|
326
|
+
wnd_item = app_item["TFrmIncluiItemPreVenda"]
|
|
327
|
+
input_almoxarifado = wnd_item.child_window(class_name="TDBIEditNumber", found_index=16)
|
|
328
|
+
input_almoxarifado.click_input()
|
|
329
|
+
await worker_sleep(1)
|
|
330
|
+
keyboard.send_keys("{END}+{HOME}{DEL}")
|
|
331
|
+
await worker_sleep(1)
|
|
332
|
+
input_almoxarifado.type_keys(almoxarifado, with_spaces=True, set_foreground=True)
|
|
333
|
+
keyboard.send_keys("{TAB}")
|
|
334
|
+
await worker_sleep(1)
|
|
335
|
+
|
|
336
|
+
# Dicionário para guardar os itens sem saldo / com saldo
|
|
337
|
+
itens_sem_saldo = {}
|
|
338
|
+
itens_com_saldo = {}
|
|
339
|
+
|
|
340
|
+
# >>> NOVO: set para acumular SOMENTE notas dos itens com saldo
|
|
341
|
+
notas_validas_set = set()
|
|
342
|
+
# (opcional) controle de notas ligadas a itens sem saldo, útil para log
|
|
343
|
+
notas_descartadas_set = set()
|
|
344
|
+
|
|
345
|
+
# =============== LOOP POR ITEM (USANDO DADOS DA API) ===============
|
|
346
|
+
for item in data["itens"]:
|
|
347
|
+
await worker_sleep(2)
|
|
348
|
+
# Abre tela de inclusão de item
|
|
349
|
+
app_item = Application().connect(class_name="TFrmIncluiItemPreVenda")
|
|
350
|
+
wnd_item = app_item["TFrmIncluiItemPreVenda"]
|
|
351
|
+
codigo = str(item["codigo"])
|
|
352
|
+
quantidade = str(item["quantidade"])
|
|
353
|
+
val_unitario = f"{float(item['valor_unitario']):.2f}".replace(".", ",")
|
|
354
|
+
item_notas = item.get("notas", [])
|
|
355
|
+
|
|
356
|
+
# --- Código ---
|
|
357
|
+
console.print("Inserir código...")
|
|
358
|
+
input_codigo = wnd_item.child_window(class_name="TDBIEditNumber", found_index=15)
|
|
359
|
+
input_codigo.click_input()
|
|
360
|
+
await worker_sleep(1)
|
|
361
|
+
keyboard.send_keys("{END}+{HOME}{DEL}")
|
|
362
|
+
await worker_sleep(1)
|
|
363
|
+
input_codigo.type_keys(codigo, with_spaces=True, set_foreground=True)
|
|
364
|
+
keyboard.send_keys("{TAB}")
|
|
365
|
+
await worker_sleep(1)
|
|
366
|
+
|
|
367
|
+
# --- Unidade (UNI) ---
|
|
368
|
+
console.print("Selecionar Unidade...")
|
|
369
|
+
select_uni = wnd_item.child_window(class_name="TDBIComboBox", found_index=1)
|
|
370
|
+
try:
|
|
371
|
+
select_uni.select("UNI")
|
|
372
|
+
except Exception:
|
|
373
|
+
select_uni.set_focus()
|
|
374
|
+
select_uni.expand()
|
|
375
|
+
await worker_sleep(1)
|
|
376
|
+
select_uni.type_keys("UNI", with_spaces=True, set_foreground=True)
|
|
377
|
+
keyboard.send_keys("{ENTER}")
|
|
378
|
+
keyboard.send_keys("{TAB}")
|
|
379
|
+
await worker_sleep(1)
|
|
380
|
+
|
|
381
|
+
# --- Quantidade ---
|
|
382
|
+
console.print("Inserir quantidade...")
|
|
383
|
+
wnd_item.child_window(class_name="TDBIEditNumber", found_index=8).click_input()
|
|
384
|
+
await worker_sleep(1)
|
|
385
|
+
keyboard.send_keys("{END}+{HOME}{DEL}")
|
|
386
|
+
await worker_sleep(1)
|
|
387
|
+
keyboard.send_keys(quantidade)
|
|
388
|
+
keyboard.send_keys("{TAB}")
|
|
389
|
+
await worker_sleep(1)
|
|
390
|
+
|
|
391
|
+
# --- Valor Unitário via popup ---
|
|
392
|
+
console.print("Inserir valor unitário...")
|
|
393
|
+
wnd_item.child_window(class_name="TDBIEditNumber", found_index=6).click_input()
|
|
394
|
+
await worker_sleep(1)
|
|
395
|
+
keyboard.send_keys("{TAB}")
|
|
396
|
+
await worker_sleep(1)
|
|
397
|
+
keyboard.send_keys("{ENTER}")
|
|
398
|
+
await worker_sleep(1)
|
|
399
|
+
|
|
400
|
+
app_preco = Application().connect(class_name="TFrmInputBoxNumero")
|
|
401
|
+
wnd_preco = app_preco["TFrmInputBoxNumero"]
|
|
402
|
+
|
|
403
|
+
campo_preco = wnd_preco.child_window(class_name="TDBIEditNumber", found_index=0)
|
|
404
|
+
campo_preco.click_input()
|
|
405
|
+
await worker_sleep(1)
|
|
406
|
+
keyboard.send_keys("{END}+{HOME}{DEL}")
|
|
407
|
+
await worker_sleep(1)
|
|
408
|
+
campo_preco.type_keys(val_unitario, with_spaces=True, set_foreground=True)
|
|
409
|
+
await worker_sleep(1)
|
|
410
|
+
wnd_preco.child_window(class_name="TBitBtn", found_index=1).click_input()
|
|
411
|
+
await worker_sleep(2)
|
|
412
|
+
|
|
413
|
+
# --- Confirmar Incluir ---
|
|
414
|
+
console.print("Confirmar inclusão do item...")
|
|
415
|
+
app_prevenda = Application().connect(class_name="TFrmIncluiItemPreVenda")
|
|
416
|
+
wnd_prevenda = app_prevenda["TFrmIncluiItemPreVenda"]
|
|
417
|
+
botao_incluir = wnd_prevenda.child_window(title="&Incluir", class_name="TDBIBitBtn").wrapper_object()
|
|
418
|
+
botao_incluir.click_input()
|
|
419
|
+
|
|
420
|
+
await worker_sleep(4)
|
|
421
|
+
|
|
422
|
+
# ================== VERIFICAÇÃO DE SALDO ==================
|
|
423
|
+
# >>> REESCRITO para deixar claro had_saldo e alimentar notas_validas_set
|
|
424
|
+
had_saldo = True
|
|
425
|
+
try:
|
|
426
|
+
console.print("Verificar mensagem de saldo menor....")
|
|
427
|
+
img_saldo = r"C:\Users\automatehub\Documents\GitHub\worker-assets\emsys\saldo_menor.png"
|
|
428
|
+
img_saldo_bool = False
|
|
429
|
+
|
|
430
|
+
for _ in range(10):
|
|
431
|
+
pos = pyautogui.locateCenterOnScreen(img_saldo, confidence=0.9)
|
|
432
|
+
if pos:
|
|
433
|
+
console.print(f"Saldo disponível menor para o item {codigo}: {quantidade} x {val_unitario}")
|
|
434
|
+
|
|
435
|
+
# adiciona no dicionário de erros
|
|
436
|
+
itens_sem_saldo[codigo] = {
|
|
437
|
+
"quantidade": quantidade,
|
|
438
|
+
"valor_unitario": val_unitario
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
# fecha a mensagem
|
|
442
|
+
app = Application().connect(class_name="TMessageForm")
|
|
443
|
+
main_window_msg = app["TMessageForm"]
|
|
444
|
+
btn_no = main_window_msg.child_window(title="&No", class_name="TButton")
|
|
445
|
+
btn_no.click_input()
|
|
446
|
+
|
|
447
|
+
# clica em limpar
|
|
448
|
+
app = Application().connect(class_name="TFrmIncluiItemPreVenda")
|
|
449
|
+
main_window_limpa = app["TFrmIncluiItemPreVenda"]
|
|
450
|
+
btn_limpa = main_window_limpa.child_window(title="&Limpa", class_name="TDBIBitBtn")
|
|
451
|
+
btn_limpa.click_input()
|
|
452
|
+
|
|
453
|
+
img_saldo_bool = True
|
|
454
|
+
had_saldo = False
|
|
455
|
+
break
|
|
456
|
+
await worker_sleep(1)
|
|
457
|
+
|
|
458
|
+
await worker_sleep(3)
|
|
459
|
+
|
|
460
|
+
if img_saldo_bool:
|
|
461
|
+
# saldo menor que quantidade
|
|
462
|
+
# (já inserido em itens_sem_saldo; também marcaremos as notas deste item como descartadas)
|
|
463
|
+
for n in item_notas:
|
|
464
|
+
notas_descartadas_set.add(str(n))
|
|
465
|
+
continue
|
|
466
|
+
|
|
467
|
+
except Exception:
|
|
468
|
+
# Se der algum erro na verificação da imagem, assumimos sucesso (com saldo)
|
|
469
|
+
had_saldo = True
|
|
470
|
+
|
|
471
|
+
# Se teve saldo, registra e marca notas válidas
|
|
472
|
+
if had_saldo:
|
|
473
|
+
console.print(f"Item {codigo} incluído com sucesso.")
|
|
474
|
+
itens_com_saldo[codigo] = {
|
|
475
|
+
"quantidade": quantidade,
|
|
476
|
+
"valor_unitario": val_unitario
|
|
477
|
+
}
|
|
478
|
+
for n in item_notas:
|
|
479
|
+
notas_validas_set.add(str(n))
|
|
480
|
+
continue
|
|
481
|
+
|
|
482
|
+
# Depois de processar todos os itens:
|
|
483
|
+
if itens_sem_saldo and not itens_com_saldo:
|
|
484
|
+
# Todos os itens ficaram sem saldo → para aqui
|
|
485
|
+
log_msg = "Todos os itens estão com saldo menor que a quantidade:\n" + \
|
|
486
|
+
"\n".join(f"- Código: {cod} | Quantidade: {dados['quantidade']} | Valor Unitário: {dados['valor_unitario']}"
|
|
487
|
+
for cod, dados in itens_sem_saldo.items())
|
|
488
|
+
return RpaRetornoProcessoDTO(
|
|
489
|
+
sucesso=False,
|
|
490
|
+
retorno=log_msg.strip(),
|
|
491
|
+
status=RpaHistoricoStatusEnum.Falha,
|
|
492
|
+
tags=[RpaTagDTO(descricao=RpaTagEnum.Negocio)]
|
|
493
|
+
)
|
|
494
|
+
|
|
495
|
+
# Caso contrário, existe pelo menos 1 com saldo → segue o fluxo
|
|
496
|
+
console.print("Há itens com saldo. Continuando o fluxo até o final...")
|
|
497
|
+
|
|
498
|
+
try:
|
|
499
|
+
# Liberação de preço (se aparecer)
|
|
500
|
+
app = Application().connect(class_name="TFrmUsuariosLiberacaoPreco")
|
|
501
|
+
login = app.window(class_name="TFrmUsuariosLiberacaoPreco")
|
|
502
|
+
login.child_window(class_name="TEdit", found_index=0).click_input()
|
|
503
|
+
login.type_keys("rpa.marvin", with_spaces=True, set_foreground=True)
|
|
504
|
+
login.child_window(class_name="TEdit", found_index=1).click_input()
|
|
505
|
+
login.type_keys("cba321", with_spaces=True, set_foreground=True)
|
|
506
|
+
login.child_window(class_name="TBitBtn", found_index=0).click_input()
|
|
507
|
+
except:
|
|
508
|
+
pass
|
|
509
|
+
|
|
510
|
+
# Clicar em fechar
|
|
511
|
+
wnd_prevenda.close()
|
|
512
|
+
|
|
513
|
+
await worker_sleep(3)
|
|
514
|
+
|
|
515
|
+
# Clicar em recebimentos
|
|
516
|
+
console.print("Clicar em recebimentos...")
|
|
517
|
+
imagem_item = r"C:\Users\automatehub\Desktop\img_leo\btn_recebimentos.png"
|
|
518
|
+
for _ in range(10):
|
|
519
|
+
pos = pyautogui.locateCenterOnScreen(imagem_item, confidence=0.9)
|
|
520
|
+
if pos:
|
|
521
|
+
pyautogui.doubleClick(pos)
|
|
522
|
+
break
|
|
523
|
+
await worker_sleep(1)
|
|
524
|
+
else:
|
|
525
|
+
print("Imagem do item não encontrada na tela.")
|
|
526
|
+
|
|
527
|
+
await worker_sleep(3)
|
|
528
|
+
|
|
529
|
+
# Clicar em Parcelamento
|
|
530
|
+
console.print("Clicar em parcelamento...")
|
|
531
|
+
imagem_parc = r"C:\Users\automatehub\Desktop\img_leo\btn_parcelamento.png"
|
|
532
|
+
for _ in range(10):
|
|
533
|
+
pos = pyautogui.locateCenterOnScreen(imagem_parc, confidence=0.8)
|
|
534
|
+
if pos:
|
|
535
|
+
pyautogui.doubleClick(pos)
|
|
536
|
+
break
|
|
537
|
+
await worker_sleep(1)
|
|
538
|
+
else:
|
|
539
|
+
print("Imagem do item não encontrada na tela.")
|
|
540
|
+
|
|
541
|
+
await worker_sleep(3)
|
|
542
|
+
|
|
543
|
+
# Volta pra janela de pre venda
|
|
544
|
+
app = Application().connect(class_name="TFrmPreVenda")
|
|
545
|
+
main_window = app["TFrmPreVenda"]
|
|
546
|
+
|
|
547
|
+
# Condição de recebimento (boleto)
|
|
548
|
+
console.print("Selecionar boleto...")
|
|
549
|
+
condicao_field = main_window.child_window(class_name="TDBIComboBox", found_index=0)
|
|
550
|
+
try:
|
|
551
|
+
condicao_field.select("BANCO DO BRASIL BOLETO")
|
|
552
|
+
print("Selecionado: BANCO DO BRASIL BOLETO")
|
|
553
|
+
except Exception as e:
|
|
554
|
+
print(f"Não foi possível selecionar 'BANCO DO BRASIL BOLETO' ({e}). Tentando 'BOLETO'...")
|
|
555
|
+
try:
|
|
556
|
+
condicao_field.select("BOLETO")
|
|
557
|
+
print("Selecionado: BOLETO")
|
|
558
|
+
except Exception as e2:
|
|
559
|
+
print(f"❌ Falha também ao selecionar 'BOLETO': {e2}")
|
|
560
|
+
|
|
561
|
+
# Clicar em Incluir
|
|
562
|
+
console.print("Incluir registro...")
|
|
563
|
+
imagem_incluir = r"C:\Users\automatehub\Documents\GitHub\worker-automate-hub\assets\entrada_notas\IncluirRegistro.png"
|
|
564
|
+
for _ in range(10):
|
|
565
|
+
pos = pyautogui.locateCenterOnScreen(imagem_incluir, confidence=0.8)
|
|
566
|
+
if pos:
|
|
567
|
+
pyautogui.click(pos)
|
|
568
|
+
break
|
|
569
|
+
await worker_sleep(1)
|
|
570
|
+
else:
|
|
571
|
+
print("Imagem do item não encontrada na tela.")
|
|
572
|
+
|
|
573
|
+
await worker_sleep(3)
|
|
574
|
+
|
|
575
|
+
# Capturar número da pré-venda
|
|
576
|
+
console.print("Capturar número da pré-venda...")
|
|
577
|
+
numero_pre_venda = None
|
|
578
|
+
timeout = 10
|
|
579
|
+
t0 = time.time()
|
|
580
|
+
while time.time() - t0 < timeout:
|
|
581
|
+
try:
|
|
582
|
+
win = Desktop(backend="win32").window(title_re=".*Informa.*")
|
|
583
|
+
if not win.exists(timeout=0.2):
|
|
584
|
+
time.sleep(0.3)
|
|
585
|
+
continue
|
|
586
|
+
win.set_focus()
|
|
587
|
+
|
|
588
|
+
textos = []
|
|
589
|
+
try: textos.append(win.window_text())
|
|
590
|
+
except: pass
|
|
591
|
+
try: textos += [t for t in win.wrapper_object().texts() if t]
|
|
592
|
+
except: pass
|
|
593
|
+
try:
|
|
594
|
+
for st in win.children(class_name="Static"):
|
|
595
|
+
textos += [t for t in st.texts() if t]
|
|
596
|
+
except: pass
|
|
597
|
+
|
|
598
|
+
texto = "\n".join([t for t in textos if t])
|
|
599
|
+
if ("Venda inclu" in texto) or ("Pré" in texto) or ("Pr" in texto):
|
|
600
|
+
m = re.search(r"\b(\d{3,}-\d{1,})\b", texto)
|
|
601
|
+
if m:
|
|
602
|
+
numero_pre_venda = m.group(1)
|
|
603
|
+
|
|
604
|
+
clicked = False
|
|
605
|
+
for title in ("OK", "&OK"):
|
|
606
|
+
try:
|
|
607
|
+
win.child_window(title=title, class_name="TButton").click_input()
|
|
608
|
+
clicked = True
|
|
609
|
+
break
|
|
610
|
+
except:
|
|
611
|
+
pass
|
|
612
|
+
if not clicked:
|
|
613
|
+
try:
|
|
614
|
+
win.type_keys("{ENTER}")
|
|
615
|
+
except:
|
|
616
|
+
pass
|
|
617
|
+
break
|
|
618
|
+
except:
|
|
619
|
+
time.sleep(0.3)
|
|
620
|
+
|
|
621
|
+
print("Número da pré-venda:", numero_pre_venda)
|
|
622
|
+
await worker_sleep(5)
|
|
623
|
+
|
|
624
|
+
# Confirmar pré-venda (Yes)
|
|
625
|
+
console.print("Confirmar pré-venda...")
|
|
626
|
+
app = Application().connect(class_name="TMessageForm")
|
|
627
|
+
main_window = app["TMessageForm"]
|
|
628
|
+
btn_ok = main_window.child_window(title="&Yes", class_name="TButton")
|
|
629
|
+
btn_ok.click_input()
|
|
630
|
+
await worker_sleep(4)
|
|
631
|
+
|
|
632
|
+
# Botão confirma
|
|
633
|
+
app = Application().connect(class_name="TFrmPreVenda")
|
|
634
|
+
main_window = app["TFrmPreVenda"]
|
|
635
|
+
btn_confirmar = main_window.child_window(title="&Confirma", class_name="TBitBtn")
|
|
636
|
+
btn_confirmar.click_input()
|
|
637
|
+
await worker_sleep(4)
|
|
638
|
+
|
|
639
|
+
# Confirmar (Yes)
|
|
640
|
+
app = Application().connect(class_name="TMessageForm")
|
|
641
|
+
main_window = app["TMessageForm"]
|
|
642
|
+
btn_confirmar = main_window.child_window(title="&Yes", class_name="TButton")
|
|
643
|
+
btn_confirmar.click_input()
|
|
644
|
+
await worker_sleep(5)
|
|
645
|
+
|
|
646
|
+
# Fechar "Informação"
|
|
647
|
+
for _ in range(10):
|
|
648
|
+
try:
|
|
649
|
+
dlg = Desktop(backend="win32").window(title_re="Informação", class_name="#32770")
|
|
650
|
+
if dlg.exists(timeout=1):
|
|
651
|
+
dlg.child_window(title="OK").click_input()
|
|
652
|
+
print("✅ Fechou janela 'Informação'.")
|
|
653
|
+
break
|
|
654
|
+
except:
|
|
655
|
+
pass
|
|
656
|
+
time.sleep(1)
|
|
657
|
+
|
|
658
|
+
await worker_sleep(3)
|
|
659
|
+
|
|
660
|
+
# Faturar
|
|
661
|
+
console.print("Clicar em faturar...")
|
|
662
|
+
app = Application().connect(class_name="TFrmPreVenda")
|
|
663
|
+
main_window = app["TFrmPreVenda"]
|
|
664
|
+
main_window.set_focus()
|
|
665
|
+
btn_faturar = main_window.child_window(title="&Faturar", class_name="TBitBtn")
|
|
666
|
+
btn_faturar.click_input()
|
|
667
|
+
await worker_sleep(5)
|
|
668
|
+
print("Botão 'Faturar' clicado com sucesso!")
|
|
669
|
+
|
|
670
|
+
# Recalcular Parcelas? (Yes)
|
|
671
|
+
console.print("Clicar em recalcular parcelas...")
|
|
672
|
+
app = Application().connect(class_name="TMessageForm")
|
|
673
|
+
main_window = app["TMessageForm"]
|
|
674
|
+
main_window.set_focus()
|
|
675
|
+
btn_confirmar = main_window.child_window(title="&Yes", class_name="TButton")
|
|
676
|
+
btn_confirmar.click_input()
|
|
677
|
+
|
|
678
|
+
for _ in range(10):
|
|
679
|
+
try:
|
|
680
|
+
dlg = Desktop(backend="win32").window(title_re="Parcelas - Nota Fiscal Sa", class_name="#32770")
|
|
681
|
+
if dlg.exists(timeout=1):
|
|
682
|
+
dlg.child_window(title="&Não").click_input()
|
|
683
|
+
print("Clicou em Não")
|
|
684
|
+
break
|
|
685
|
+
except:
|
|
686
|
+
pass
|
|
687
|
+
|
|
688
|
+
await worker_sleep(10)
|
|
689
|
+
|
|
690
|
+
# Notas referenciadas
|
|
691
|
+
console.print("CLicar em notas referenciadas...")
|
|
692
|
+
imagem_notas_ref = r"C:\Users\automatehub\Desktop\img_leo\notas_referenciadas.png"
|
|
693
|
+
for _ in range(20):
|
|
694
|
+
pos = pyautogui.locateCenterOnScreen(imagem_notas_ref, confidence=0.8)
|
|
695
|
+
if pos:
|
|
696
|
+
pyautogui.click(pos)
|
|
697
|
+
break
|
|
698
|
+
await worker_sleep(1)
|
|
699
|
+
else:
|
|
700
|
+
print("Imagem do item não encontrada na tela.")
|
|
701
|
+
|
|
702
|
+
await worker_sleep(2)
|
|
703
|
+
|
|
704
|
+
# Faturamento Pré-venda
|
|
705
|
+
app = Application().connect(class_name="TFrmDadosFaturamentoPreVenda")
|
|
706
|
+
main_window = app["TFrmDadosFaturamentoPreVenda"]
|
|
707
|
+
main_window.set_focus()
|
|
708
|
+
|
|
709
|
+
# Radio Entrada
|
|
710
|
+
main_window.child_window(title="Entrada", class_name="TDBIRadioButton").click_input()
|
|
711
|
+
console.print("Clicado em 'Entrada'")
|
|
712
|
+
await worker_sleep(4)
|
|
713
|
+
|
|
714
|
+
# ====== FILTRAR NOTAS VÁLIDAS ======
|
|
715
|
+
todas_as_notas = [str(n) for n in data.get("nf_referencia", [])]
|
|
716
|
+
notas_validas_ordenadas = [n for n in todas_as_notas if n in notas_validas_set]
|
|
717
|
+
notas_descartadas = [n for n in todas_as_notas if n not in notas_validas_set]
|
|
718
|
+
|
|
719
|
+
console.print(f"[green]Notas a referenciar (itens com saldo): {notas_validas_ordenadas}[/]")
|
|
720
|
+
if notas_descartadas:
|
|
721
|
+
console.print(f"[yellow]Notas descartadas (apenas itens sem saldo): {notas_descartadas}[/]")
|
|
722
|
+
|
|
723
|
+
# >>> NOVO: nota_arquivo (primeira válida; fallback: pré-venda ou timestamp) - SEM extract_nf_number
|
|
724
|
+
if notas_validas_ordenadas:
|
|
725
|
+
nota_arquivo = re.sub(r"\D+", "", str(notas_validas_ordenadas[0])) or str(notas_validas_ordenadas[0])
|
|
726
|
+
else:
|
|
727
|
+
if numero_pre_venda:
|
|
728
|
+
nota_arquivo = re.sub(r"\D+", "", str(numero_pre_venda)) or str(numero_pre_venda)
|
|
729
|
+
else:
|
|
730
|
+
nota_arquivo = datetime.now().strftime("%Y%m%d%H%M%S")
|
|
731
|
+
|
|
732
|
+
# === LOOP REFERENCIANDO APENAS NOTAS VÁLIDAS ===
|
|
733
|
+
for nf_ref_atual in notas_validas_ordenadas:
|
|
734
|
+
itens_da_nota = data.get("itens_por_nota", {}).get(nf_ref_atual, [])
|
|
735
|
+
if not itens_da_nota:
|
|
736
|
+
console.print(f"[amarelo]Nenhum item associado à nota {nf_ref_atual}. Pulando...[/]")
|
|
737
|
+
continue
|
|
738
|
+
|
|
739
|
+
console.print(f"[cyan]Processando nota {nf_ref_atual}...[/]")
|
|
740
|
+
|
|
741
|
+
# 1) Focar e limpar o campo da nota
|
|
742
|
+
input_num_nota = main_window.child_window(class_name="TDBIEditDescription")
|
|
743
|
+
input_num_nota.set_focus()
|
|
744
|
+
try:
|
|
745
|
+
input_num_nota.select() # alguns campos suportam select()
|
|
746
|
+
except Exception:
|
|
747
|
+
pass
|
|
748
|
+
keyboard.send_keys("^a{DEL}") # Ctrl+A + Delete (fallback)
|
|
749
|
+
await worker_sleep(0.4)
|
|
750
|
+
|
|
751
|
+
# 2) Digitar a nota e confirmar
|
|
752
|
+
input_num_nota.type_keys(str(nf_ref_atual), with_spaces=True, set_foreground=True)
|
|
753
|
+
await worker_sleep(0.6)
|
|
754
|
+
keyboard.send_keys("{ENTER}")
|
|
755
|
+
await worker_sleep(0.6)
|
|
756
|
+
|
|
757
|
+
# Clicar em incluir itens (folha de papel com +)
|
|
758
|
+
app = Application().connect(class_name="TFrmDadosFaturamentoPreVenda")
|
|
759
|
+
main_window = app["TFrmDadosFaturamentoPreVenda"]
|
|
760
|
+
|
|
761
|
+
# Clica no botão identificado como TDBIBitBtn2 (control_id 918912)
|
|
762
|
+
main_window.child_window(class_name="TDBIBitBtn", found_index=1).click_input()
|
|
763
|
+
|
|
764
|
+
print("Botão clicado com sucesso!")
|
|
765
|
+
console.print(f"Incluindo itens vinculados à nota {nf_ref_atual}...")
|
|
766
|
+
|
|
767
|
+
# Aba mensagens
|
|
768
|
+
console.print("Clicar em mensagens...")
|
|
769
|
+
imagem_notas_ref = r"C:\Users\automatehub\Desktop\img_leo\aba_mensagem.png"
|
|
770
|
+
for _ in range(10):
|
|
771
|
+
pos = pyautogui.locateCenterOnScreen(imagem_notas_ref, confidence=0.9)
|
|
772
|
+
if pos:
|
|
773
|
+
pyautogui.click(pos)
|
|
774
|
+
break
|
|
775
|
+
await worker_sleep(1)
|
|
776
|
+
else:
|
|
777
|
+
print("Imagem do item não encontrada na tela.")
|
|
778
|
+
await worker_sleep(5)
|
|
779
|
+
|
|
780
|
+
# Mensagem interna
|
|
781
|
+
imagem_notas_ref = r"C:\Users\automatehub\Desktop\img_leo\mensagem_interna.png"
|
|
782
|
+
for _ in range(10):
|
|
783
|
+
pos = pyautogui.locateCenterOnScreen(imagem_notas_ref, confidence=0.8)
|
|
784
|
+
if pos:
|
|
785
|
+
pyautogui.click(pos)
|
|
786
|
+
break
|
|
787
|
+
await worker_sleep(1)
|
|
788
|
+
else:
|
|
789
|
+
print("Imagem do item não encontrada na tela.")
|
|
790
|
+
await worker_sleep(4)
|
|
791
|
+
|
|
792
|
+
# Inserir mensagem padrão
|
|
793
|
+
console.print("Inserir mensagem...")
|
|
794
|
+
fornecedor = "Disbal"
|
|
795
|
+
lista_fornecedores = ["Disbal", "Pepsico", "Punta Balena"]
|
|
796
|
+
mensagem = "PRODUTOS VENCIDOS" if fornecedor in lista_fornecedores else "ACORDO COMERCIAL"
|
|
797
|
+
input_mensagem = main_window.child_window(class_name="TDBIMemo", found_index=0)
|
|
798
|
+
input_mensagem.type_keys(mensagem, with_spaces=True, set_foreground=True)
|
|
799
|
+
|
|
800
|
+
# Aba itens
|
|
801
|
+
imagem_itens = r"C:\Users\automatehub\Desktop\img_leo\aba_itens.png"
|
|
802
|
+
for _ in range(10):
|
|
803
|
+
pos = pyautogui.locateCenterOnScreen(imagem_itens, confidence=0.9)
|
|
804
|
+
if pos:
|
|
805
|
+
pyautogui.click(pos)
|
|
806
|
+
break
|
|
807
|
+
await worker_sleep(1)
|
|
808
|
+
else:
|
|
809
|
+
print("Imagem do item não encontrada na tela.")
|
|
810
|
+
|
|
811
|
+
await worker_sleep(3)
|
|
812
|
+
|
|
813
|
+
# Corrige tributação
|
|
814
|
+
console.print("Corrigir tributação...")
|
|
815
|
+
imagem_itens = r"C:\Users\automatehub\Desktop\img_leo\corrige_tributacao.png"
|
|
816
|
+
for _ in range(10):
|
|
817
|
+
pos = pyautogui.locateCenterOnScreen(imagem_itens, confidence=0.9)
|
|
818
|
+
if pos:
|
|
819
|
+
pyautogui.click(pos)
|
|
820
|
+
break
|
|
821
|
+
await worker_sleep(1)
|
|
822
|
+
else:
|
|
823
|
+
print("Imagem do tributacao não encontrada na tela.")
|
|
824
|
+
|
|
825
|
+
await worker_sleep(3)
|
|
826
|
+
|
|
827
|
+
# Selecionar tributação
|
|
828
|
+
console.print("Selecionar tributação...")
|
|
829
|
+
app = Application().connect(class_name="TFrmDadosTributacaoProdutoPreVenda")
|
|
830
|
+
trib = app["TFrmDadosTributacaoProdutoPreVenda"]
|
|
831
|
+
|
|
832
|
+
if estado == "RS":
|
|
833
|
+
select_trib = trib.child_window(class_name="TDBIComboBox", found_index=4)
|
|
834
|
+
select_trib.select("051 - 051 - ICMS 17% RED BC 29,4118% - TRIBUT.CORRETA")
|
|
835
|
+
print("Selecionado: 051 - 051 - ICMS 17% RED BC 29,4118% - TRIBUT.CORRETA")
|
|
836
|
+
elif estado == "SC":
|
|
837
|
+
select_trib = trib.child_window(class_name="TDBIComboBox", found_index=4)
|
|
838
|
+
select_trib.select("000 - 000 - ICMS - 12%")
|
|
839
|
+
print("Selecionado: 000 - 000 - ICMS - 12%")
|
|
840
|
+
else:
|
|
841
|
+
print("Estado diferente dos mapeados")
|
|
842
|
+
|
|
843
|
+
if fornecedor == "Disbal":
|
|
844
|
+
select_trib.select("020 - 020 - ICMS 12% RED. BASE 41,667")
|
|
845
|
+
elif fornecedor == "Punta Balena":
|
|
846
|
+
select_trib.select("000 - 000 - ICMS - 12%")
|
|
847
|
+
elif fornecedor == "Vitrola":
|
|
848
|
+
select_trib.select("041 - 041 - ICMS - NAO INCIDENTE ")
|
|
849
|
+
|
|
850
|
+
await worker_sleep(2)
|
|
851
|
+
|
|
852
|
+
trib.child_window(title="&OK", class_name="TBitBtn").click_input()
|
|
853
|
+
|
|
854
|
+
await worker_sleep(1)
|
|
855
|
+
|
|
856
|
+
# Aba principal
|
|
857
|
+
imagem_principal = r"C:\Users\automatehub\Desktop\img_leo\aba_principal.png"
|
|
858
|
+
for _ in range(10):
|
|
859
|
+
pos = pyautogui.locateCenterOnScreen(imagem_principal, confidence=0.9)
|
|
860
|
+
if pos:
|
|
861
|
+
pyautogui.click(pos)
|
|
862
|
+
break
|
|
863
|
+
await worker_sleep(1)
|
|
864
|
+
else:
|
|
865
|
+
print("Imagem do item não encontrada na tela.")
|
|
866
|
+
|
|
867
|
+
await worker_sleep(5)
|
|
868
|
+
|
|
869
|
+
# DANFE 077
|
|
870
|
+
console.print("Selecionar NFe - NOTA FISCAL ELETRONICA PROPRIA - DANFE SERIE 077...")
|
|
871
|
+
app = Application().connect(class_name="TFrmDadosFaturamentoPreVenda")
|
|
872
|
+
main_window = app["TFrmDadosFaturamentoPreVenda"]
|
|
873
|
+
select_danfe = main_window.child_window(class_name="TDBIComboBox", found_index=1)
|
|
874
|
+
select_danfe.select("NFe - NOTA FISCAL ELETRONICA PROPRIA - DANFE SERIE 077")
|
|
875
|
+
|
|
876
|
+
await worker_sleep(2)
|
|
877
|
+
|
|
878
|
+
# OK
|
|
879
|
+
main_window.child_window(title="&OK", class_name="TBitBtn").click_input()
|
|
880
|
+
|
|
881
|
+
await worker_sleep(3)
|
|
882
|
+
|
|
883
|
+
# Faturar pré-venda (Yes)
|
|
884
|
+
app = Application().connect(class_name="TMessageForm")
|
|
885
|
+
main_window = app["TMessageForm"]
|
|
886
|
+
main_window.child_window(class_name="TButton", found_index=1).click()
|
|
887
|
+
|
|
888
|
+
await worker_sleep(5)
|
|
889
|
+
|
|
890
|
+
# Faturar pré-venda (Yes)
|
|
891
|
+
app = Application().connect(class_name="TMessageForm")
|
|
892
|
+
main_window = app["TMessageForm"]
|
|
893
|
+
main_window.child_window(title="Transmitir e &Imprimir", class_name="TButton").click_input()
|
|
894
|
+
|
|
895
|
+
await worker_sleep(10)
|
|
896
|
+
|
|
897
|
+
# Diálogo impressão
|
|
898
|
+
console.print("Confirmar impressão...")
|
|
899
|
+
app = Application().connect(class_name="TppPrintDialog")
|
|
900
|
+
main_window = app["TppPrintDialog"]
|
|
901
|
+
main_window.child_window(title="OK", class_name="TButton").click()
|
|
902
|
+
|
|
903
|
+
await worker_sleep(5)
|
|
904
|
+
|
|
905
|
+
console.print(f"NAVEGANDO NA TELA DE SALVAR RELATORIO\n")
|
|
906
|
+
# INSERINDO O DIRETORIO E SALVANDO O ARQUIVO
|
|
907
|
+
try:
|
|
908
|
+
app = Application().connect(title="Salvar Saída de Impressão como")
|
|
909
|
+
main_window = app["Dialog"]
|
|
910
|
+
console.print("Tela 'Salvar' encontrada!")
|
|
911
|
+
|
|
912
|
+
console.print("Interagindo com a tela 'Salvar'...\n")
|
|
913
|
+
username = getpass.getuser()
|
|
914
|
+
|
|
915
|
+
# Preenche o nome do arquivo - SOMENTE número da nota
|
|
916
|
+
path_to_txt = f"C:\\Users\\{username}\\Downloads\\devolucao_nf_{estado}_{nota_arquivo}"
|
|
917
|
+
|
|
918
|
+
main_window.type_keys("%n")
|
|
919
|
+
pyautogui.write(path_to_txt)
|
|
920
|
+
await worker_sleep(1)
|
|
921
|
+
main_window.type_keys("%l")
|
|
922
|
+
console.print("Arquivo salvo com sucesso...\n")
|
|
923
|
+
await worker_sleep(8)
|
|
924
|
+
except Exception as e:
|
|
925
|
+
retorno = f"Não foi salvar o arquivo: {e}"
|
|
926
|
+
return RpaRetornoProcessoDTO(
|
|
927
|
+
sucesso=False,
|
|
928
|
+
retorno=retorno,
|
|
929
|
+
status=RpaHistoricoStatusEnum.Falha,
|
|
930
|
+
tags=[RpaTagDTO(descricao=RpaTagEnum.Tecnico)]
|
|
931
|
+
)
|
|
932
|
+
|
|
933
|
+
with open(f"{path_to_txt}.pdf", 'rb') as file:
|
|
934
|
+
file_bytes = io.BytesIO(file.read())
|
|
935
|
+
|
|
936
|
+
desArquivo = f"devolucao_nf_{estado}_{nota_arquivo}.pdf"
|
|
937
|
+
try:
|
|
938
|
+
await send_file(historico_id, desArquivo, "pdf", file_bytes, file_extension="pdf")
|
|
939
|
+
os.remove(f"{path_to_txt}.pdf")
|
|
940
|
+
except Exception as e:
|
|
941
|
+
result = (
|
|
942
|
+
f"Arquivo gerado com sucesso, porém erro ao enviar para o backoffice: {e} "
|
|
943
|
+
f"- Arquivo salvo em {path_to_txt}.pdf"
|
|
944
|
+
)
|
|
945
|
+
console.print(result, style="bold red")
|
|
946
|
+
return RpaRetornoProcessoDTO(
|
|
947
|
+
sucesso=False,
|
|
948
|
+
retorno=result,
|
|
949
|
+
status=RpaHistoricoStatusEnum.Falha,
|
|
950
|
+
tags=[RpaTagDTO(descricao=RpaTagEnum.Tecnico)]
|
|
951
|
+
)
|
|
952
|
+
|
|
953
|
+
except Exception as ex:
|
|
954
|
+
log_msg = f"Error: {ex}"
|
|
955
|
+
print(ex)
|
|
956
|
+
return RpaRetornoProcessoDTO(
|
|
957
|
+
sucesso=False, retorno=log_msg, status=RpaHistoricoStatusEnum.Falha, tags=[RpaTagDTO(descricao=RpaTagEnum.Negocio)]
|
|
958
|
+
)
|
|
959
|
+
|
|
960
|
+
# ============== RESUMO FINAL ==============
|
|
961
|
+
def _fmt_linha(cod, dados):
|
|
962
|
+
return f"- Código: {cod} | Quantidade: {dados.get('quantidade')} | Valor Unitário: {dados.get('valor_unitario')}"
|
|
963
|
+
|
|
964
|
+
resumo_partes = []
|
|
965
|
+
|
|
966
|
+
if itens_com_saldo:
|
|
967
|
+
lista_ok = "\n".join(_fmt_linha(c, d) for c, d in list(itens_com_saldo.items()))
|
|
968
|
+
resumo_partes.append("✅ Itens incluídos:\n" + (lista_ok if lista_ok else "(vazio)"))
|
|
969
|
+
|
|
970
|
+
if itens_sem_saldo:
|
|
971
|
+
lista_sem = "\n".join(_fmt_linha(c, d) for c, d in list(itens_sem_saldo.items()))
|
|
972
|
+
resumo_partes.append("⚠️ Itens sem saldo:\n" + (lista_sem if lista_sem else "(vazio)"))
|
|
973
|
+
|
|
974
|
+
# (Opcional) resumo sobre notas válidas/descartadas
|
|
975
|
+
try:
|
|
976
|
+
resumo_partes.append(
|
|
977
|
+
"🧾 Notas referenciadas: " + ", ".join(sorted(list(notas_validas_set))) if notas_validas_set else "🧾 Notas referenciadas: (nenhuma)"
|
|
978
|
+
)
|
|
979
|
+
except:
|
|
980
|
+
pass
|
|
981
|
+
|
|
982
|
+
resumo_txt = "\n\n".join(resumo_partes) if resumo_partes else "Nenhum item processado."
|
|
983
|
+
|
|
984
|
+
return RpaRetornoProcessoDTO(
|
|
985
|
+
sucesso=True,
|
|
986
|
+
retorno=f"Processo concluído.\n\n{resumo_txt}",
|
|
987
|
+
status=RpaHistoricoStatusEnum.Sucesso,
|
|
988
|
+
tags=[RpaTagDTO(descricao=RpaTagEnum.Negocio)]
|
|
989
|
+
)
|
|
990
|
+
|
|
991
|
+
|
|
@@ -33,7 +33,9 @@ from worker_automate_hub.tasks.jobs.entrada_de_notas_36 import entrada_de_notas_
|
|
|
33
33
|
from worker_automate_hub.tasks.jobs.entrada_de_notas_37 import entrada_de_notas_37
|
|
34
34
|
from worker_automate_hub.tasks.jobs.entrada_de_notas_503 import entrada_de_notas_503
|
|
35
35
|
from worker_automate_hub.tasks.jobs.extracao_saldo_estoque import extracao_saldo_estoque
|
|
36
|
-
from worker_automate_hub.tasks.jobs.extracao_saldo_estoque_fiscal import
|
|
36
|
+
from worker_automate_hub.tasks.jobs.extracao_saldo_estoque_fiscal import (
|
|
37
|
+
extracao_saldo_estoque_fiscal,
|
|
38
|
+
)
|
|
37
39
|
from worker_automate_hub.tasks.jobs.fidc_remessa_cobranca_cnab240 import (
|
|
38
40
|
remessa_cobranca_cnab240,
|
|
39
41
|
)
|
|
@@ -109,6 +111,9 @@ from worker_automate_hub.tasks.jobs.geracao_balancetes_filial import (
|
|
|
109
111
|
geracao_balancetes_filial,
|
|
110
112
|
)
|
|
111
113
|
|
|
114
|
+
from worker_automate_hub.tasks.jobs.devolucao_produtos import (
|
|
115
|
+
devolucao_produtos,
|
|
116
|
+
)
|
|
112
117
|
|
|
113
118
|
task_definitions = {
|
|
114
119
|
"5b295021-8df7-40a1-a45e-fe7109ae3902": exemplo_processo,
|
|
@@ -216,7 +221,8 @@ task_definitions = {
|
|
|
216
221
|
"9cbc6016-7c0e-4a3a-8ee9-fb9dc4b35e33": extracao_saldo_estoque_fiscal,
|
|
217
222
|
"07072711-c9d0-49e4-b180-530cecbe0728": opex_capex,
|
|
218
223
|
"98bc6679-2e6b-4757-9fdc-b27eebd98f54": entrada_de_notas_22,
|
|
219
|
-
"
|
|
224
|
+
"2ebcc2e5-2fa1-4130-a92a-3af349a1920c": devolucao_produtos,
|
|
225
|
+
"d7794924-0330-453c-b79b-74f3c8991562": geracao_balancetes_filial,
|
|
220
226
|
}
|
|
221
227
|
|
|
222
228
|
|
|
@@ -722,10 +722,23 @@ async def login_emsys_old(
|
|
|
722
722
|
)
|
|
723
723
|
|
|
724
724
|
#Login novo
|
|
725
|
-
async def login_emsys(config: dict, app, task: RpaProcessoEntradaDTO, **kwargs):
|
|
726
|
-
#
|
|
727
|
-
|
|
728
|
-
|
|
725
|
+
async def login_emsys(config: dict, app, task: RpaProcessoEntradaDTO, filial_origem=None, **kwargs):
|
|
726
|
+
# Fonte de verdade: param explícito > kwargs > task.configEntrada
|
|
727
|
+
filial_origem = (
|
|
728
|
+
filial_origem
|
|
729
|
+
or kwargs.get("filial_origem")
|
|
730
|
+
or kwargs.get("descricaoFilial")
|
|
731
|
+
or (getattr(task, "configEntrada", {}) or {}).get("descricaoFilial")
|
|
732
|
+
or (getattr(task, "configEntrada", {}) or {}).get("codigoEmpresa")
|
|
733
|
+
or (getattr(task, "configEntrada", {}) or {}).get("filialEmpresaOrigem")
|
|
734
|
+
)
|
|
735
|
+
|
|
736
|
+
# Extrai só o número (ex.: "69" de "69 - Gravataí Free Way")
|
|
737
|
+
if filial_origem:
|
|
738
|
+
m = re.search(r"\d+", str(filial_origem))
|
|
739
|
+
if m:
|
|
740
|
+
filial_origem = m.group(0)
|
|
741
|
+
|
|
729
742
|
warnings.filterwarnings(
|
|
730
743
|
"ignore",
|
|
731
744
|
category=UserWarning,
|
|
@@ -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=
|
|
4
|
+
worker_automate_hub/api/client.py,sha256=efug1qAm_5i3eEYwu6bnJjREJP0UpUTjmaYIDcItV04,35614
|
|
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
|
|
@@ -45,6 +45,7 @@ worker_automate_hub/tasks/jobs/descartes.py,sha256=wIi8n4vZrNE-03C5_lr4FmxuKoWSY
|
|
|
45
45
|
worker_automate_hub/tasks/jobs/devolucao_ctf.py,sha256=7tdUihaDqjIf7POjM79EqKG0w-qqXbhC6jq6hteavkw,250822
|
|
46
46
|
worker_automate_hub/tasks/jobs/devolucao_ctf_35.py,sha256=e9t5k2mtZcUcEGKPWysbWzsH_gqrK-6aBXjWe2jWfTg,253948
|
|
47
47
|
worker_automate_hub/tasks/jobs/devolucao_prazo_a_faturar.py,sha256=kzPJazDRbz2CLn8tKja2Lg1N4UzTRF1V4Nc1elIqTGY,272145
|
|
48
|
+
worker_automate_hub/tasks/jobs/devolucao_produtos.py,sha256=PDqS4kPtYWbsbIy0AiG05CtWQFRowEfhfHpiZsaKySg,40975
|
|
48
49
|
worker_automate_hub/tasks/jobs/ecac_estadual_go.py,sha256=dKkf22nH5gp3RErq5u0UzRsKyJ81fc6ZZ4vLtUuMwHA,21002
|
|
49
50
|
worker_automate_hub/tasks/jobs/ecac_estadual_main.py,sha256=8WmKe4-MRtzHobXz2S4YBDNN8alfawkC-BBlRY-mn1g,1726
|
|
50
51
|
worker_automate_hub/tasks/jobs/ecac_estadual_mt.py,sha256=C26zmpGQGUq6sP9lU9nanM3Fje-rkyx5tjwmRy4lyL8,25300
|
|
@@ -93,7 +94,7 @@ worker_automate_hub/tasks/jobs/opex_capex.py,sha256=RbifCpmacvWAbV3tAabee_I0dxb9
|
|
|
93
94
|
worker_automate_hub/tasks/jobs/playground.py,sha256=7vWDg9DwToHwGJ6_XOa8TQ6LmfRV5Qz2TaOV3q3P9sA,1918
|
|
94
95
|
worker_automate_hub/tasks/jobs/sped_fiscal.py,sha256=rinyHCF7QYHUc6oWACJgnQiAv0S-_Fel9Z0bImiHUoM,31064
|
|
95
96
|
worker_automate_hub/tasks/jobs/transferencias.py,sha256=5TIktufkvUPnVTR2gf7GFQJ5KQP6PWnmoWiE08WiVDQ,46191
|
|
96
|
-
worker_automate_hub/tasks/task_definitions.py,sha256=
|
|
97
|
+
worker_automate_hub/tasks/task_definitions.py,sha256=L4f5ZJ8lSyBwASFwRh0S3RlhvH--gXn6d4RBHVORX3k,13164
|
|
97
98
|
worker_automate_hub/tasks/task_executor.py,sha256=F5ngJLGz7vbUrX-batUlt3FFwiCE8denFmtTTLaE77I,6044
|
|
98
99
|
worker_automate_hub/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
99
100
|
worker_automate_hub/utils/env.py,sha256=TacQjGRO7PUNpttrhTAc5Gnegaiysl2Knsv1P8qfkfs,57
|
|
@@ -101,10 +102,10 @@ worker_automate_hub/utils/get_creds_gworkspace.py,sha256=ZJ0IIEjM4IXIV9rwfbOZ1V1
|
|
|
101
102
|
worker_automate_hub/utils/logger.py,sha256=FYV9fg0_RAYJF_ZOCJEbqQAiCXlXk2gMpvUU1rzT_xs,671
|
|
102
103
|
worker_automate_hub/utils/toast.py,sha256=xPHc5r5uOxB_cZlCzm13Kt2qSKLLFZALncU6Qg3Ft68,1162
|
|
103
104
|
worker_automate_hub/utils/updater.py,sha256=en2FCGhI8aZ-JNP3LQm64NJDc4awCNW7UhbVlwDl49Y,7972
|
|
104
|
-
worker_automate_hub/utils/util.py,sha256=
|
|
105
|
+
worker_automate_hub/utils/util.py,sha256=rDp5h36I_kMfaCDD9xgcxibRXe5AYaImlXKhGbQ7DHE,211273
|
|
105
106
|
worker_automate_hub/utils/utils_nfe_entrada.py,sha256=F7jk95LpDwl5WfaQXahCA5yDdnySnWdctDqczHXwGqE,38195
|
|
106
107
|
worker_automate_hub/worker.py,sha256=zEnYUrm5kY2cHbbee15QJkwkx4euD2SB2zRvUIbjS90,6850
|
|
107
|
-
worker_automate_hub-0.5.
|
|
108
|
-
worker_automate_hub-0.5.
|
|
109
|
-
worker_automate_hub-0.5.
|
|
110
|
-
worker_automate_hub-0.5.
|
|
108
|
+
worker_automate_hub-0.5.829.dist-info/entry_points.txt,sha256=sddyhjx57I08RY8X7UxcTpdoOsWULAWNKN9Xr6pp_Kw,54
|
|
109
|
+
worker_automate_hub-0.5.829.dist-info/METADATA,sha256=p2nNX9hVoMfEnfrA9bnxcuuwijv7yii2MprLtwB9JIU,3142
|
|
110
|
+
worker_automate_hub-0.5.829.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
|
|
111
|
+
worker_automate_hub-0.5.829.dist-info/RECORD,,
|
|
File without changes
|
{worker_automate_hub-0.5.828.dist-info → worker_automate_hub-0.5.829.dist-info}/entry_points.txt
RENAMED
|
File without changes
|