🪐 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
- Visão geral dos módulos
- Configuração de logging
- 1. siafelibrary — SIAFE-Rio2
- 2. seilibrary — SEI
- 3. apipoint — SharePoint e Microsoft Graph
- Referência do
dict_map - Arquivos de XPath
- Arquitetura e decisões de design
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 Edge deve estar instalado e atualizado. O
automawebgerencia o MSEdgeDriver automaticamente. A instalação dooffice365-rest-python-clientvia git exige que ogitesteja 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:
- Arquivo geral — mensagens
INFO,WARNINGeERROR; - Arquivo de erros — apenas
ERROR; - 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 | ✅ | — |
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_EVougerar_PDT_API);df— um DataFrame com os lançamentos;dict_map— dicionário de regras contábeis por tipo (ver Referência dodict_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="ORGAO")
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=Trueevita reabrir o processo quandoadicionar_marcadoré chamado logo apósremover_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, usando a API CSOM do SharePoint via office365-rest-python-client (requer instalação manual antes do jupiter-subtes).
Autenticação. Não usa usuário/senha nem registro de aplicativo no Azure AD — a conexão reaproveita cookies de uma sessão de navegador já autenticada:
- Na primeira conexão (ou sempre que os cookies expirarem), o construtor abre automaticamente uma janela do Microsoft Edge apontando para o
site_urlinformado. A pessoa precisa fazer o login manualmente nessa janela; feito isso, os cookies são salvos em disco e a janela fecha sozinha. - Os cookies ficam salvos, por padrão, em
~/Downloads/cookies_SharePoint.json. Use o parâmetrocaminho_cookiedo construtor para customizar esse caminho — útil se você usa mais de uma conta/site, ou roda em máquinas diferentes. - Automações sem interface gráfica (servidor, serviço do Windows, agendador): se a conexão falhar, o construtor exibe um popup de erro (Tkinter
messagebox.showerror), o que pode travar um processo headless em vez de simplesmente lançar uma exceção. Rode a primeira conexão manualmente (com tela) para gerar o arquivo de cookies antes de colocar a rotina para rodar sem interação, e garanta que o arquivo de cookies acompanhe a máquina/usuário que vai executar a automação. - Configure o log antes de instanciar
SharePoint(veja Configuração de logging): a maioria dos métodos abaixo não lança exceção em caso de falha, então sem log configurado você não terá nenhum rastro do que deu errado.
Caminhos. caminho_sharepoint / pasta_sharepoint usam o caminho relativo ao servidor (server-relative URL), no formato /sites/NomeDoSite/Shared Documents/Pasta/arquivo.txt.
from jupiter import SharePoint
sp = SharePoint(site_url="https://tenant.sharepoint.com/sites/SetorContabil")
# Arquivos — download_arquivo/upload_arquivo retornam bool (True em caso de sucesso)
if not sp.download_arquivo(
caminho_sharepoint="/sites/SetorContabil/Shared Documents/Relatorios/balancete.xlsx",
pasta_local="C:/Users/joao/Downloads",
):
print("Falha ao baixar o balancete — verifique o log.")
if not sp.upload_arquivo(
caminho_local="C:/Users/joao/Downloads/resultado_julho.xlsx",
pasta_sharepoint="/sites/SetorContabil/Shared Documents/Resultados",
):
print("Falha ao enviar o resultado — verifique o log.")
# Pastas (recursivo nos dois sentidos) — também retornam bool
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 | Retorno |
|---|---|---|
download_arquivo / upload_arquivo |
Transferência de arquivo único | bool — True em caso de sucesso, False se falhar |
download_pasta / upload_pasta |
Transferência recursiva de pastas | bool — True somente se todos os arquivos/subpastas forem transferidos com sucesso |
criar_pasta |
Cria a estrutura de pastas (garante o caminho) | bool — True em caso de sucesso, False se falhar |
existe_arquivo / existe_pasta |
Verificação de existência | bool — False se não existir; lança ValueError para outros erros (ex.: sem permissão) |
excluir_arquivo / excluir_pasta |
Remoção | None — lança a exceção original em caso de falha |
Os quatro primeiros métodos nunca lançam exceção: qualquer falha é registrada no log (
configurar_log) e sinalizada apenas pelo retornoFalse. Jáexcluir_arquivo/excluir_pastapropagam a exceção — envolva-os emtry/exceptse for uma operação crítica.
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@orgao.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@orgao.rj.gov.br", "chefia@orgao.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://orgao.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@orgao.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@orgao.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": Truequando 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.
Siafenão contém nenhum código de conta, fonte ou UG. Tudo é injetado viadict_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
StaleElementReferenceExceptione aguardam o cursor sair do estado de carregamento antes de prosseguir. - Persistência incremental.
gerar_documentoinvocacallback_sucessoa 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_logpadroniza os logs de todos os módulos, eGraphAPI.notificar_erro/enviar_loglevam falhas e relatórios para o Teams e o Outlook. - A biblioteca não abre janelas. Nenhum método exibe caixas de diálogo: as falhas vão para o log (e, na API, para
siafe.ultimo_erro_API) e o retorno indica o resultado. Quem decide o que mostrar ao usuário é o programa chamador. Isso permite rodar em subprocesso, serviço ou agendador sem travar esperando um clique. - Consulta de documentos por filtro. Os métodos
dicionario_*pedem ao SIAFE apenas o documento-modelo, via POST com o número no corpo da requisição, em vez de baixar todos os documentos da UG no exercício para filtrar localmente.
Release files for jupiter-subtes 1.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| jupiter_subtes-1.2.0.tar.gz | 67.6 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| jupiter_subtes-1.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 126.8 kB
Release files / jupiter_subtes-1.2.0.tar.gz
| Download URL | jupiter_subtes-1.2.0.tar.gz |
|---|---|
| Size | 67.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
04a84c963fd6a7fd58230856aeb145ccb24a6ef24ddeea91af24228479998c8d
|
|
BLAKE2b-256 checksum How to use checksums |
eb92862bcd7a97a0d88c0aee71496bf5cfea8bf126c3e6b4c23a1797b6239cf5
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.6
|
Release files / jupiter_subtes-1.2.0-py3-none-any.whl
| Download URL | jupiter_subtes-1.2.0-py3-none-any.whl |
|---|---|
| Size | 59.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
1dafd53ba90f3db386218e3ab536b8d5e4d1bcb566047b3d7fa273da54048d39
|
|
BLAKE2b-256 checksum How to use checksums |
e32862f83e9861c2992a9fb55e9524c827c213e953f762624526c94c85a5f714
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.6
|