Skip to main content

Biblioteca para modernização do fluxo de trabalho do Tesouro do Estado do Rio de Janeiro

Project description

🪐 jupiter-subtes

jupiter-subtes é uma biblioteca Python para automação dos fluxos de trabalho do Tesouro do Estado do Rio de Janeiro. Ela unifica, em um único pacote, três domínios de automação:

  • SIAFE-Rio2 — geração de documentos contábeis (GR, PDE, PDT, NP, NA, EV) por interface web e por API REST;
  • SEI — controle de processos, análise de documentos, despachos, anexos e marcadores;
  • Microsoft 365 — SharePoint (arquivos e pastas) e Microsoft Graph (Outlook e Teams).

A biblioteca é genérica: não contém regras de negócio codificadas (contas, fontes, UGs). Toda a parametrização contábil é injetada em tempo de execução por dicionários, permitindo que o mesmo código atenda a diferentes setores sem alteração no fonte.

from jupiter import Siafe, SEI, SharePoint, GraphAPI, configurar_log

Índice


Instalação

O módulo apipoint (SharePoint e Graph) depende de uma versão específica do office365-rest-python-client que ainda não foi publicada no PyPI. Instale-a a partir do repositório oficial antes do jupiter:

pip install git+https://github.com/vgrem/office365-rest-python-client.git@630e4e1f7977e28a8354174cc85896421425e4d7
pip install jupiter-subtes

Se você não utilizará o módulo apipoint, a instalação simples é suficiente:

pip install jupiter-subtes

Dependências

Biblioteca Instalação Uso
selenium >= 4.0.0 automática Controle do navegador
automaweb automática Camada base de automação web (interna)
pandas automática Manipulação de DataFrames
requests automática Chamadas às APIs REST (SIAFE, SEI, Teams)
msal automática Suporte à autenticação Microsoft
office365-rest-python-client manual (ver acima) SharePoint e Graph

Requisitos de ambiente: o Google Chrome deve estar instalado e atualizado. O automaweb gerencia o ChromeDriver automaticamente. A instalação do office365-rest-python-client via git exige que o git esteja disponível na máquina.


Visão geral dos módulos

Módulo Classes / funções Domínio
siafelibrary Siafe Automação web e API do SIAFE-Rio2
seilibrary SEI Automação web do SEI
apipoint SharePoint, GraphAPI, configurar_log SharePoint, Outlook, Teams e logging

As classes Siafe e SEI herdam de automaweb.Navegador e gerenciam o próprio navegador. SharePoint e GraphAPI operam exclusivamente por API.


Configuração de logging

A biblioteca não registra nenhum handler por conta própria — todos os módulos emitem logs sob o logger jupiter. A função configurar_log centraliza a configuração e deve ser chamada antes de instanciar qualquer classe.

Ela cria até três destinos para os registros:

  1. Arquivo geral — mensagens INFO, WARNING e ERROR;
  2. Arquivo de erros — apenas ERROR;
  3. Interface gráfica — opcional, via callback (para exibir mensagens ao usuário em tempo real).
import logging
from jupiter import configurar_log, Siafe

# Configura os arquivos de log (chame no início do programa)
caminho_geral, caminho_erros = configurar_log(
    nome_programa="Rotina de Contabilização",
    pasta_geral="C:/Logs/geral",
    pasta_erros="C:/Logs/erros",
    callback_interface=None,   # ou uma função que recebe str, ex.: self.log
)

# Loggers do seu programa também são capturados se usarem o prefixo "jupiter."
log = logging.getLogger("jupiter.main")
log.info("Iniciando automação")

siafe = Siafe()   # a partir daqui, todos os logs do Siafe são gravados nos arquivos

Alternativamente, você pode configurar o logger jupiter manualmente com a API padrão do logging, caso precise de um formato ou destino específico.


1. siafelibrary — SIAFE-Rio2

A classe Siafe encapsula toda a interação com o SIAFE-Rio2, tanto pela interface web quanto pela API REST.

1.1. Autenticação

from jupiter import Siafe

siafe = Siafe()

# Login pela interface web (necessário para geração de documentos via navegador)
sucesso = siafe.logar_siafe(versaoSiafe=1, usuario="12345678900", senha="senha")

# Login pela API REST (necessário para métodos *_API e consulta_flexvision)
siafe.logar_siafe_API(versaoSiafe=1, usuario="12345678900", senha="senha")

Ambientes disponíveis (versaoSiafe):

Valor Ambiente Web API
1 Produção
2 Beta / Testes
3 Homologação
4 SIAFE-Rio 1 (legado)

logar_siafe retorna True/False e trata internamente o pop-up de credenciais inválidas. logar_siafe_API armazena o token em siafe.token e o reutiliza nas chamadas subsequentes.

1.2. Geração de documentos em lote

O método gerar_documento é o ponto de entrada para contabilização em lote. Ele recebe:

  • funcao — o método gerador do documento (gerar_GR, gerar_PDE, gerar_PDT, gerar_NP, gerar_NA, gerar_EV ou gerar_PDT_API);
  • df — um DataFrame com os lançamentos;
  • dict_map — dicionário de regras contábeis por tipo (ver Referência do dict_map);
  • callback_sucesso — função opcional chamada a cada documento contabilizado.
Método Documento
gerar_GR Guia de Recolhimento (orçamentária e extra-orçamentária)
gerar_PDE Programação de Desembolso Extra-orçamentária
gerar_PDT Programação de Desembolso de Transferência
gerar_NP Nota Patrimonial
gerar_NA Nota de Aplicação e Resgate
gerar_EV Nota de Evento (múltiplos itens)
gerar_PDT_API PDT enviada diretamente pela API REST

O DataFrame deve conter, no mínimo, as colunas: id, data, valor, observacao, tipo_id, além de num_documento e tempo_contab inicializadas como None (o robô as preenche).

import pandas as pd
from jupiter import Siafe

df = pd.DataFrame([
    {"id": 1, "data": "01/07/2025", "valor": 1500.00,
     "observacao": "Recolhimento referente a julho/2025",
     "tipo_id": "GR_FUNDO_A", "num_documento": None, "tempo_contab": None},
    {"id": 2, "data": "01/07/2025", "valor": 3200.50,
     "observacao": "Recolhimento referente a julho/2025",
     "tipo_id": "GR_FUNDO_B", "num_documento": None, "tempo_contab": None},
])

regras = {
    "GR_FUNDO_A": { ... },   # ver "Referência do dict_map"
    "GR_FUNDO_B": { ... },
}

def ao_contabilizar(id, num_documento, tempo_contab):
    print(f"[OK] id={id}  doc={num_documento}  tempo={tempo_contab}s")
    # persista o resultado no banco, planilha ou SharePoint aqui

siafe = Siafe()
if siafe.logar_siafe(versaoSiafe=1, usuario="12345678900", senha="senha"):
    siafe.gerar_documento(
        funcao=siafe.gerar_GR,
        df=df,
        dict_map=regras,
        callback_sucesso=ao_contabilizar,
    )

O callback_sucesso é chamado a cada documento gerado, permitindo persistência incremental — se a rotina for interrompida, os documentos já contabilizados estão salvos e o DataFrame reprocessa apenas as linhas com num_documento ainda vazio.

1.3. Nota de Evento (EV) com múltiplos itens

Diferente dos demais, a gerar_EV recebe os itens em um DataFrame aninhado no próprio dicionário, na chave itens (colunas id, evento, credor, valor):

import pandas as pd

regras_ev = {
    "EV_FOLHA": {
        "UG":  "123456",
        "IEF": "1",
        "itens": pd.DataFrame([
            {"id": 1, "evento": "540101", "credor": "12345678000199", "valor": 1000.00},
            {"id": 2, "evento": "540102", "credor": "98765432000155", "valor":  750.50},
        ]),
    },
}

siafe.gerar_documento(funcao=siafe.gerar_EV, df=df, dict_map=regras_ev)

Para duplicar uma Nota de Evento já existente alterando apenas a data e a observação:

siafe.copiar_EV(num_doc="2025EV000123", nova_data="01/08/2025", nova_obs="Reemissão agosto/2025")

1.4. Geração de PDT pela API REST

Para PDTs, além do fluxo web, a biblioteca oferece um caminho por API — mais rápido e sem navegador. O fluxo tem duas etapas: obter a estrutura de uma PDT-modelo com dicionario_PDT e enviá-la com gerar_PDT_API.

from jupiter import Siafe

siafe = Siafe()
siafe.logar_siafe_API(versaoSiafe=1, usuario="12345678900", senha="senha")

# 1. Monta o dicionário-base a partir de uma PDT existente (usada como modelo)
modelo = siafe.dicionario_PDT(exercicio=2025, codigoUG=123456, num_documento="2025PD000045")

# 2a. Envio individual
num_doc, tempo = siafe.gerar_PDT_API(
    exercicio=2025,
    dicionario=modelo,
    data="01/07/2025",
    valor=1500.00,
    observacao="Transferência referente a julho/2025",
)

# 2b. Ou em lote, reutilizando gerar_documento
siafe.gerar_documento(
    funcao=siafe.gerar_PDT_API,
    df=df,
    dict_map={"PDT_MODELO": modelo},
    callback_sucesso=ao_contabilizar,
)

1.5. Consultas e impressão de GR

# Relatório do FlexVision via API (retorna um DataFrame)
df_relatorio = siafe.consulta_flexvision(id="12345", parametros_consulta="2025,123456")

# Imprime em PDF todas as GRs do DataFrame (após gerar_documento preencher num_documento)
siafe.consultar_GR_numDoc(df=df, callback_sucesso=lambda id: print(f"PDF gerado: id={id}"))

# Localiza e imprime uma GR pelo valor (e, opcionalmente, pela data de recolhimento)
num_doc = siafe.consultar_GR_valor(
    valor_pesquisa=1500.00,
    versaoSiafe=1,
    data_pagamento="01/07/2025",
)

2. seilibrary — SEI

A classe SEI automatiza o Sistema Eletrônico de Informações: navegação em processos, análise de documentos, despachos, anexos e gestão de marcadores.

2.1. Login e controle de processos

from jupiter import SEI

sei = SEI()
sei.logar_sei(usuario="joao.silva", senha="senha", orgao="SEFAZ")
sei.trocar_unidade("SUPCONC")

# Retorna todos os processos do Controle de Processos, com todas as colunas
# (processo, atribuicao, tipo, marcadores, controle_prazo, etc.)
processos = sei.controlar_processos()

for p in processos:
    print(p["processo"], "|", p["tipo"], "|", p["marcadores"])

2.2. Marcadores

# Lista todos os processos de um marcador específico
todos = sei.visualizar_processos_por_marcador(marcador="Aguardando Despacho")

# Filtra localmente os processos que possuem determinado marcador
pendentes = sei.filtrar_processos_por_marcador(todos, marcador="Aguardando Despacho")

# Move um processo de um marcador para outro
sei.pesquisar_processo("0012345-67.2025.8.19.0000")
sei.remover_marcador("0012345-67.2025.8.19.0000")
sei.adicionar_marcador(marcador="Concluído", processo="0012345-67.2025.8.19.0000", flag_removido=True)

flag_removido=True evita reabrir o processo quando adicionar_marcador é chamado logo após remover_marcador.

2.3. Análise de documentos

analisar_documentos percorre a árvore do processo e retorna um dicionário {nome_documento: texto}. Sobre esse resultado, três métodos aplicam diferentes critérios de busca:

Método Critério Retorno
verificar_despacho OR (qualquer termo) lista de documentos
verificar_despacho_estrito AND (todos os termos) lista de documentos
verificar_despacho_detalhado quais termos por documento {documento: [termos]}
sei.pesquisar_processo("0012345-67.2025.8.19.0000")
sei.expandir_pastas()

# Analisa apenas documentos cujo nome contém "Memorando"
documentos = sei.analisar_documentos(condicao="Memorando")

# Documentos que mencionem "pagamento" E "autorizado"
com_ambos = sei.verificar_despacho_estrito(documentos, termos_busca=["pagamento", "autorizado"])

# Mapa detalhado: quais termos foram achados em cada documento
mapa = sei.verificar_despacho_detalhado(
    documentos, termos_busca=["pagamento", "autorizado", "pendente"]
)
for doc, termos in mapa.items():
    print(f"{doc}: {termos}")

2.4. Download de documentos

baixar_documento localiza um documento pelo nome na árvore e salva o PDF localmente — funciona tanto para documentos externos quanto para documentos natos do SEI.

sei.pesquisar_processo("0012345-67.2025.8.19.0000")
sei.expandir_pastas()

if sei.baixar_documento(nome_documento="Balancete Julho 2025"):
    print("Documento baixado com sucesso.")

2.5. Anexos, despachos e blocos de assinatura

sei.pesquisar_processo("0012345-67.2025.8.19.0000")

# Inclui um arquivo externo como Anexo
sei.incluir_anexo(
    nome_arvore="Balancete Julho 2025",
    caminho_arquivo="C:/Users/joao/Downloads/balancete_jul25.pdf",
    nivel_acesso="publico",   # ou "restrito" (exige hipotese_legal)
)

# Cria um Despacho a partir de um texto padrão cadastrado no SEI.
# Retorna True somente se o despacho for confirmado na árvore do processo.
if sei.incluir_despacho(texto_padrao="Encaminhamento SUPCONC"):

    # Preenche as variáveis do modelo no editor CKEditor5 do SEI
    numero_gr = sei.copiar_informacoes_documento()   # nº do último documento da árvore
    sei.formatar_despacho(
        titulo="Senhor Coordenador,",
        valor="1.500,00",
        valor_por_extenso="um mil e quinhentos reais",
        data="01/07/2025",
        num_documento=numero_gr,
        index_doc=numero_gr,
    )

    # Encaminha o processo para assinatura
    sei.incluir_processo_bloco(bloco="Bloco Assinatura Mensal")

3. apipoint — SharePoint e Microsoft Graph

3.1. SharePoint

A classe SharePoint gerencia arquivos e pastas de um site corporativo. A autenticação usa cookies do navegador, coletados automaticamente via automaweb na primeira conexão e persistidos em disco.

from jupiter import SharePoint

sp = SharePoint(site_url="https://tenant.sharepoint.com/sites/SetorContabil")

# Arquivos
sp.download_arquivo(
    caminho_sharepoint="/sites/SetorContabil/Shared Documents/Relatorios/balancete.xlsx",
    pasta_local="C:/Users/joao/Downloads",
)
sp.upload_arquivo(
    caminho_local="C:/Users/joao/Downloads/resultado_julho.xlsx",
    pasta_sharepoint="/sites/SetorContabil/Shared Documents/Resultados",
)

# Pastas (recursivo nos dois sentidos)
sp.download_pasta("/sites/SetorContabil/Shared Documents/Backup", "C:/Users/joao/Backup_SP")
sp.upload_pasta("C:/Users/joao/Relatorios/2025", "/sites/SetorContabil/Shared Documents/2025")

# Verificações e estrutura
if not sp.existe_pasta("/sites/SetorContabil/Shared Documents/2025/Julho"):
    sp.criar_pasta("/sites/SetorContabil/Shared Documents/2025/Julho")

if sp.existe_arquivo("/sites/SetorContabil/Shared Documents/2025/Junho/temp.xlsx"):
    sp.excluir_arquivo("/sites/SetorContabil/Shared Documents/2025/Junho/temp.xlsx")

sp.excluir_pasta("/sites/SetorContabil/Shared Documents/2025/Rascunhos")
Método Ação
download_arquivo / upload_arquivo Transferência de arquivo único
download_pasta / upload_pasta Transferência recursiva de pastas
criar_pasta Cria a estrutura de pastas (garante o caminho)
existe_arquivo / existe_pasta Verificação de existência
excluir_arquivo / excluir_pasta Remoção

3.2. Microsoft Graph (Outlook e Teams)

A classe GraphAPI usa autenticação app-only (client credentials) para integrar com Outlook e Teams. Requer registro de aplicativo no Azure AD e autorização da TI para a conta corporativa.

from jupiter import GraphAPI

graph = GraphAPI(
    tenant_id="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
    client_id="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
    client_secret="seu-segredo-aqui",
    conta_corporativa="automacao@sefaz.rj.gov.br",
)

# Outlook — envio, resposta e leitura
graph.enviar_email(
    titulo="Rotina de julho concluída",
    mensagem="A contabilização de 47 GRs foi finalizada com sucesso.",
    destinatarios=["joao.silva@sefaz.rj.gov.br", "chefia@sefaz.rj.gov.br"],
)
mensagens = graph.listar_emails(pasta="Inbox", top=5)
graph.responder_email(id_mensagem="AAMkAGI...", texto_resposta="Recebido, em processamento.")
pastas = graph.listar_pastas()
contatos = graph.obter_contatos()

# Teams — mensagem via webhook
graph.enviar_mensagem(
    webhook_url="https://sefaz.webhook.office.com/webhookb2/...",
    mensagem="Contabilização de julho finalizada.",
    destinatarios=["equipe-contabil"],
)

Notificação de erros e envio de logs

GraphAPI também serve como canal de monitoramento das rotinas. notificar_erro reporta exceções e enviar_log despacha o conteúdo de um arquivo de log — ambos por Teams e/ou Outlook.

try:
    siafe.gerar_documento(funcao=siafe.gerar_GR, df=df, dict_map=regras)
except Exception as e:
    graph.notificar_erro(
        excecao=e,
        contexto="Contabilização de GR — lote de julho",
        webhook_url=WEBHOOK,
        destinatarios=["suporte@sefaz.rj.gov.br"],
    )

# Ao final da rotina, envia o log de erros gerado por configurar_log
graph.enviar_log(
    caminho_log=caminho_erros,
    titulo="Log de erros — Rotina de julho",
    destinatarios=["suporte@sefaz.rj.gov.br"],
)

Referência do dict_map

O dict_map é o mecanismo central de separação entre regras de negócio e automação. Cada chave corresponde ao valor da coluna tipo_id no DataFrame; o valor é um dicionário com os campos que o SIAFE exige para aquele tipo de documento.

regras = {

    # ── GR Orçamentária ──────────────────────────────────────────────────────
    "GR_ORC": {
        "TipoDocumento":             "01 - Arrecadação",         # texto exato do dropdown
        "UG":                        "123456",                    # código da UG emitente
        "DomicilioBancario":         "0001",                      # código para pesquisa
        "DomicilioBancarioCompleto": "0001 - BANCO DO BRASIL",    # texto para validação
        "ExtraOrcamentario":         False,

        "IEF":                       "1",
        "Fonte":                     "100",
        "FonteRJ":                   "100",
        "TipoDetalhamentoFonte":     "0",
        "DetalhamentoFonte":         "0000",                      # opcional
        "Convenio":                  "99999",

        "TipoPatrimonial":           "Ativo",
        "ItemPatrimonial":           "Bancos Conta Movimento",
        "OperacaoPatrimonial":       "Entrada de Recursos",
        "NaturezaReceita":           "11180111",                  # exclusivo da GR orçamentária
    },

    # ── GR Extra-orçamentária ────────────────────────────────────────────────
    "GR_EXTRA": {
        "TipoDocumento":             "02 - Extra-orçamentário",
        "UG":                        "654321",
        "DomicilioBancario":         "0002",
        "DomicilioBancarioCompleto": "0002 - CAIXA ECONÔMICA FEDERAL",
        "ExtraOrcamentario":         True,                        # ativa o caminho extra-orçamentário

        "IEF": "1", "Fonte": "100", "FonteRJ": "100",
        "TipoDetalhamentoFonte": "0", "Convenio": "99999",

        "TipoPatrimonial":           "Passivo",
        "ItemPatrimonial":           "Obrigações a Pagar",
        "OperacaoPatrimonial":       "Saída de Recursos",

        "TipoCredor":                "PJ",                        # PJ | PF | CG | UG (padrão: PJ)
        "Credor":                    "12345678000199",
    },

    # ── PDT (Programação de Desembolso de Transferência) ─────────────────────
    "PDT_01": {
        "UG":                               "123456",
        "UGFavorecida":                     "654321",             # opcional; padrão = UG
        "DomicilioBancarioOrigem":          "0001",
        "DomicilioBancarioOrigemCompleto":  "0001 - BANCO DO BRASIL",
        "DomicilioBancarioDestino":         "0002",
        "DomicilioBancarioDestinoCompleto": "0002 - CAIXA",

        "IEF": "1", "Fonte": "100", "FonteRJ": "100",
        "TipoDetalhamentoFonte": "0", "DetalhamentoFonte": "0000", "Convenio": "99999",

        "TipoPatrimonial":                  "Ativo",
        "ItemPatrimonial":                  "Transferências",
        "OperacaoPatrimonial":              "899991",
        "SelecaoPorValor":                  True,                 # seleciona pelo código, não pelo texto

        "Regularizacao":                    "01 - Tipo A",        # opcional
        "JustificativaRegularizacao":       "Regularização do mês anterior",  # opcional
    },

    # ── NP com Inscrição Genérica ────────────────────────────────────────────
    "NP_IG": {
        "UG":                        "123456",
        "TipoPatrimonial":           "Ativo",
        "ItemPatrimonial":           "Ajustes Patrimoniais",
        "OperacaoPatrimonial":       "Bloqueio",
        "SelecaoPorValor":           True,

        "IEF": "1", "Fonte": "100", "FonteRJ": "100",
        "TipoDetalhamentoFonte": "0", "DetalhamentoFonte": "0000",
        "DomicilioBancario":         "0001",

        "InscricaoGenerica":         "12345",                     # opcional
        "TipoInscricaoGenerica":     "01 - Bloqueio",             # opcional
    },

    # ── NA com Estorno ───────────────────────────────────────────────────────
    "NA_ESTORNO": {
        "UG":                        "123456",
        "Estorno":                   True,                        # marca o documento como estorno

        "TipoPatrimonial":           "Ativo",
        "ItemPatrimonial":           "Aplicações Financeiras",
        "OperacaoPatrimonial":       "Resgate",
        "IEF": "1", "Fonte": "100", "FonteRJ": "100",
        "TipoDetalhamentoFonte": "0", "DetalhamentoFonte": "0000",
        "DomicilioBancario":         "0001 - BANCO DO BRASIL",
    },
}

Boas práticas

  • Os textos dos dropdowns devem ser exatamente iguais aos exibidos no SIAFE (copie diretamente da tela).
  • Use "SelecaoPorValor": True quando o dropdown tem muitas opções e é mais confiável selecionar pelo código numérico.
  • Para PDT via API, o dicionário tem estrutura diferente (JSON de payload) e deve ser obtido com dicionario_PDT, não montado manualmente.

Arquivos de XPath

Os módulos siafelibrary_xpaths.py e seilibrary_xpaths.py centralizam os seletores XPath de cada tela. Quando o SIAFE ou o SEI atualizam a interface, basta ajustar o arquivo _xpaths.py correspondente — a lógica de negócio permanece intacta.

siafelibrary_xpaths.py — por tela do SIAFE:

Classe Tela
siafe_xpaths_login Login
xpaths_menu Menu de navegação
xpaths_gr Guia de Recolhimento
xpaths_pde PD Extra-orçamentária
xpaths_pdt PD de Transferência
xpaths_np Nota Patrimonial
xpaths_na Nota de Aplicação e Resgate
xpaths_ev Nota de Evento
xpaths_consulta Filtros de consulta de GR

seilibrary_xpaths.py — por área do SEI:

Classe Área
sei_xpaths_login Login
xpaths_pagina_inicial Barra de pesquisa e menu da unidade
xpaths_processos Árvore de documentos e iframes
xpaths_documento Formulário de inclusão de documento
xpaths_controle_processos Tabela do Controle de Processos
from jupiter import xpaths_gr, siafe_xpaths_login, sei_xpaths_login

print(xpaths_gr.btn_inserir_gr)      # '//*[@id="pt1:tblGuiaRecolhimento:btnInsert"]'
print(siafe_xpaths_login.usuario)    # '//*[@id="loginBox:itxUsuario::content"]'
print(sei_xpaths_login.btn_acessar)  # '//*[@id="sbmAcessar"]'

Estendendo a biblioteca

from jupiter import Siafe, xpaths_gr

class SiafeCustom(Siafe):
    def verificar_numero_gr(self) -> str | None:
        """Retorna o número da GR exibido na tela atual."""
        if self.verifica_visivel(xpaths_gr.numero_documento):
            return self.obter_texto(xpaths_gr.numero_documento)
        return None

Arquitetura e decisões de design

  • Separação de regras de negócio. Siafe não contém nenhum código de conta, fonte ou UG. Tudo é injetado via dict_map, permitindo que a mesma biblioteca atenda a diferentes sub-setores sem alterações no fonte.
  • Validação antes de prosseguir. Após cada preenchimento crítico, o robô relê o campo do SIAFE para confirmar que o valor foi aceito. Se a validação falhar, ele aborta o documento (clicando em "Voltar") e tenta novamente — até 3 tentativas por lançamento.
  • Resiliência a falhas de DOM. Os métodos de interação têm retry automático para StaleElementReferenceException e aguardam o cursor sair do estado de carregamento antes de prosseguir.
  • Persistência incremental. gerar_documento invoca callback_sucesso a cada documento gerado. Se o processo cair na metade, os documentos já contabilizados estão salvos e apenas os pendentes são reprocessados.
  • Dois caminhos para o SIAFE. Operações podem ser feitas pela interface web (robusta, cobre todos os documentos) ou pela API REST (mais rápida, disponível para PDT e consultas), conforme a necessidade.
  • XPaths centralizados. Os seletores ficam nos arquivos _xpaths.py, isolando a manutenção das mudanças de interface do SIAFE e do SEI.
  • Observabilidade integrada. configurar_log padroniza os logs de todos os módulos, e GraphAPI.notificar_erro / enviar_log levam falhas e relatórios para o Teams e o Outlook.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

jupiter_subtes-1.1.3.tar.gz (52.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

jupiter_subtes-1.1.3-py3-none-any.whl (44.3 kB view details)

Uploaded Python 3

File details

Details for the file jupiter_subtes-1.1.3.tar.gz.

File metadata

  • Download URL: jupiter_subtes-1.1.3.tar.gz
  • Upload date:
  • Size: 52.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.14

File hashes

Hashes for jupiter_subtes-1.1.3.tar.gz
Algorithm Hash digest
SHA256 c3c8b72ad2ae85bd512721bc940ee6c303551f5ebd7bf3da194f1a5ca594d052
MD5 98c5d05fe359ef6d53fdcc4224b49f01
BLAKE2b-256 5ce85c06ceac0aa894ebeef2e5485e33daa4fd066e92953e7f96bcb91a609d13

See more details on using hashes here.

File details

Details for the file jupiter_subtes-1.1.3-py3-none-any.whl.

File metadata

  • Download URL: jupiter_subtes-1.1.3-py3-none-any.whl
  • Upload date:
  • Size: 44.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.14

File hashes

Hashes for jupiter_subtes-1.1.3-py3-none-any.whl
Algorithm Hash digest
SHA256 9a4cd8cfba24fa203e69e9b2d654507865bece6b896d5edb6bbd2672926dfc27
MD5 dc46741050e2af0c464c36739ffaaee8
BLAKE2b-256 777b52f8e2eb7b093057f58102c5ec11924ca2e942b78c472cd493cf1fab65db

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page