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