Sites Latam · Sistema Interno · Facilities & RH

Hórus — Gestão de
Chamados

Sistema interno para abertura e acompanhamento de chamados de Facilities e RH. Solicitantes abrem chamados via QR Code — a equipe gerencia pelo painel autenticado.

code FastAPI + SQLAlchemy + MySQL web SPA HTML/CSS/JS Vanilla lock JWT + Bcrypt qr_code Formulário via QR Code calendar_today Atualizado: Maio 2026
Resumo Executivo

O que é o Hórus?

Uma visão direta do sistema — ideal para novos membros da equipe.

O Hórus é o sistema web interno da Sites Latam para gestão de chamados de Facilities e RH. Roda localmente via Python/FastAPI e é acessado pelo navegador. Solicitantes externos usam o formulário público (form.html) acessível via QR Code impresso. A equipe acessa o painel gerencial em index.html.

qr_code

Abertura via QR Code

Solicitantes escaneiam o QR Code impresso e preenchem o formulário público sem precisar de login. O protocolo HOR-YY-XXXX é gerado automaticamente.

list_alt

Fila de Chamados

A equipe de RH/Facilities acompanha todos os chamados em uma fila unificada. Filtros por status, urgência e período. Atribuição de responsável e acompanhamento em tempo real.

payments

Custo do Chamado

Registro financeiro de cada chamado: mão de obra, materiais, equipamentos e serviços terceirizados. Inclui fornecedor, nota de qualidade e observações.

query_stats

Dashboard Gerencial

5 KPIs em tempo real: Total, Abertos, Em Andamento, Concluídos e Custo Total. Gráficos de distribuição por urgência e por departamento.

admin_panel_settings

Administração

Gestão de usuários com controle de perfil (admin / analista). Logs de acesso e auditoria de sessões da equipe.

person

Perfis de Acesso

Admin — acesso total incluindo painel de usuários. Analista — dashboard, chamados e custo. Público — somente formulário de abertura via QR Code.

Como executar o sistema

terminal
Execute no terminal PowerShell a partir do diretório do projeto:
cd "<caminho-do-projeto>\backend"
python -m uvicorn main:app --reload --use-colors
Abra frontend/index.html diretamente no navegador. Não usar venv localmente.
Infraestrutura

Stack Técnica

Tecnologias usadas em cada camada do sistema.

FastAPI

Framework backend — API REST na porta 8000

SQLAlchemy

ORM — modelos e sessões MySQL/SQLite

MySQL (prod)

Banco de dados em produção via .env

SQLite (dev)

Fallback local — backend/horus.db

python-jose

Geração e validação de tokens JWT

passlib / bcrypt

Hash seguro de senhas

Vanilla JS

Frontend SPA — fetch API, Chart.js, qrcodejs

Outfit® / Brand

Tipografia única — Manual de Marca Sites Latam

Uvicorn

Servidor ASGI — execução local (Anaconda)

Identidade Visual — Variáveis CSS obrigatórias

/* Manual de Marca Sites Latam */ :root { --brand-red: #EB0045; /* CTAs, active state */ --brand-blue: #003E52; /* Sidebar, headers */ --brand-gray: #C1C5C8; /* Bordas secundárias */ --surface: #F4F6F8; /* Background geral */ --border: #E4E7EA; /* Bordas de cards */ --font: 'Outfit', sans-serif; }
warning
Regras obrigatórias de marca: Nunca usar outra fonte além de Outfit®. Ícones exclusivamente Material Symbols Outlined (mínimo 24px). Background decorativo em .main-content::before com opacity 0.65 — não alterar z-index dos filhos.
Técnico

Arquitetura do Sistema

Estrutura de arquivos e responsabilidade de cada componente.

Backend

ArquivoResponsabilidade
main.pyEntrypoint FastAPI — registra routers, configura CORS, monta /uploads, executa create_all na inicialização.
database.pyEngine SQLAlchemy — MySQL via .env com fallback SQLite (horus.db). Factory get_db().
models.py6 modelos ORM: Chamado, Historico, Anexo, Usuario, ValorChamado, LogAcesso. Enums: StatusChamado, UrgenciaChamado, CategoriaValor.
schemas.pySchemas Pydantic de validação de entrada e resposta para todos os modelos.
security.pyJWT com python-jose + hash bcrypt com passlib. Funções: criar_token(), get_current_user().
routers/auth.pyPOST /api/login · PATCH /api/usuarios/{email}/senha · GET /api/usuarios/{email}/status (heartbeat)
routers/chamados.pyCRUD completo de chamados com upload de anexo, geração de protocolo e registro automático de histórico.
routers/valor.pyGET / POST / DELETE de itens de custo financeiro por chamado.
routers/estatisticas.pyCards KPI (total, abertos, andamento, concluídos, custo_total) e dados para gráficos — com filtros de data e status.
routers/admin.pyCRUD de usuários (admin-only) + listagem de logs de acesso.
services/protocolo.pyGera protocolo único no formato HOR-YY-XXXX (ex: HOR-26-0001).
.envCredenciais MySQL: DB_USER, DB_PASSWORD, DB_HOST, DB_PORT, DB_NAME. Não versionar.

Frontend

ArquivoResponsabilidade
index.htmlSPA unificado — login overlay + todas as views + sidebar retrátil. API_BASE_URL em <script> no topo — única linha a alterar no deploy Linux.
form.htmlFormulário público de abertura de chamados. Acessado via QR Code. Nunca modificar.
documentacao.htmlEste documento — documentação técnica do sistema.
js/auth.jsNavegação SPA (navegarPara()), config VIEWS, authFetch(), guardião de sessão, logout.
js/chamados.jsFila de chamados, modal de detalhe, funções de Valor do Chamado e modal QR Code.
js/dashboard.js5 KPIs + 2 gráficos Chart.js (urgência e departamento).
js/admin.jsGestão de usuários (CRUD) e listagem de logs de acesso.
js/login.jsAutenticação — POST /api/login, armazena token e sessão no localStorage.
css/layout.cssDesign system global: sidebar, topbar, tabelas, KPIs, modais.

Fluxo de requisição

Navegador
(index.html)
authFetch()
+ JWT Bearer
FastAPI
(main.py)
Router
específico
SQLAlchemy
ORM
MySQL / SQLite
Banco de Dados

Tabelas e Modelos

Estrutura completa do banco — modelos ORM em backend/models.py.

check_circle
Criação automática: models.Base.metadata.create_all(bind=engine) é chamado no main.py a cada inicialização — cria tabelas novas sem dropar as existentes.
assignment tb_Horus_forms — Chamados
tb_Horus_forms PK: id
PKidINTEGERAuto increment
UKprotocoloVARCHAR(20)Protocolo único — formato HOR-YY-XXXX, gerado por services/protocolo.py
solicitanteVARCHAR(120)Nome completo do solicitante
emailVARCHAR(150)E-mail de contato do solicitante
departamentoVARCHAR(80)Departamento de origem do chamado
localVARCHAR(120)Local físico do problema
tipo_servicoVARCHAR(120)Tipo do serviço solicitado
urgenciaENUMbaixa | media | alta | critica
descricaoTEXTDescrição completa do problema
statusENUMaberto | em_andamento | concluido | cancelado
responsavel_nomeVARCHAR(100)Membro da equipe atribuído ao chamado
ip_origemVARCHAR(45)IP do solicitante — rastreio anti-trote
user_agentVARCHAR(500)User-agent do browser — rastreio anti-trote
criado_emDATETIMETimestamp de abertura (UTC)
atualizado_emDATETIMEAtualizado automaticamente a cada PATCH
concluido_emDATETIMEPreenchido quando status muda para concluido
history tb_Horus_historico — Linha do tempo do chamado
tb_Horus_historico PK: id · FK: chamado_id
PKidINTEGERAuto increment
FKchamado_idINTEGERReferência a tb_Horus_forms.id
autorVARCHAR(100)Email do usuário que realizou a ação
acaoVARCHAR(200)Descrição da ação (ex: "Status alterado para Em Andamento")
detalheTEXTObservação adicional (opcional)
criado_emDATETIMETimestamp da ação (UTC)
info
Preenchido automaticamente pelo backend em todo PATCH de chamado (mudança de status ou responsável). Também pode ser preenchido manualmente via POST /api/chamados/{id}/historico.
attach_file tb_Horus_anexos — Arquivos do chamado
tb_Horus_anexos PK: id · FK: chamado_id
PKidINTEGERAuto increment
FKchamado_idINTEGERReferência a tb_Horus_forms.id
nomeVARCHAR(255)Nome original do arquivo enviado
caminhoVARCHAR(500)Path relativo: /uploads/{uuid}{extensao} — servido como static file
tipoVARCHAR(50)MIME type (ex: image/jpeg, application/pdf)
criado_emDATETIMETimestamp do upload (UTC)
payments tb_Horus_valor_chamado — Custos financeiros
tb_Horus_valor_chamado PK: id · FK: chamado_id
PKidINTEGERAuto increment
FKchamado_idINTEGERReferência a tb_Horus_forms.id
categoriaENUMmao_de_obra | material | equipamento | servico_terceiro | outros
valor_reaisNUMERIC(10,2)Valor em reais com 2 casas decimais
fornecedor_nomeVARCHAR(150)Nome do fornecedor ou prestador
fornecedor_contatoVARCHAR(150)Contato do fornecedor (telefone/email)
nota_qualidadeINTEGERAvaliação de 1 a 5 estrelas
obs_qualidadeTEXTObservação sobre a qualidade do serviço
preenchido_porVARCHAR(100)Email do usuário que registrou o custo
criado_emDATETIMETimestamp do registro (UTC)
person tb_Horus_usuarios — Equipe autenticada
tb_Horus_usuarios PK: id · UK: email
PKidINTEGERAuto increment
UKemailVARCHAR(150)Identificador único — usado no login e no token JWT
senha_hashVARCHAR(255)Senha hasheada com bcrypt via passlib
perfilVARCHAR(50)admin | analista
ativoBOOLEANFalse = usuário bloqueado (não consegue logar)
ultimo_acessoDATETIMEAtualizado no heartbeat de sessão (a cada 10s)
criado_emDATETIMETimestamp de criação do usuário (UTC)
receipt_long tb_Horus_logs — Auditoria de sessões
tb_Horus_logs PK: id · FK: usuario_id
PKidINTEGERAuto increment
FKusuario_idINTEGERReferência a tb_Horus_usuarios.id
email_usuarioVARCHAR(150)Denormalizado para facilitar consultas de auditoria
criado_emDATETIMETimestamp do evento de acesso (UTC)
Módulo Principal

Fluxo Completo do Chamado

Da abertura via QR Code até o encerramento pela equipe.

1

Abertura via QR Code

Solicitante escaneia o QR Code impresso no local. Abre form.html no navegador do celular — sem necessidade de login. Preenche nome, e-mail, departamento, local, tipo de serviço, urgência e descrição. Pode anexar uma foto.

2

Geração do Protocolo

O backend (POST /api/chamados) chama gerar_protocolo(db) que cria um código único no formato HOR-YY-XXXX. O IP e user-agent do solicitante são registrados como rastreio anti-trote.

3

Triagem pela equipe

Analista acessa index.html, faz login e navega para "Fila de Chamados". O chamado aparece com status aberto. A equipe atribui responsável e altera status para em_andamento.

4

Execução e registro de custo

Durante a execução, a equipe pode registrar itens de custo (mão de obra, materiais, etc.) diretamente no modal do chamado. Cada item aceita fornecedor e nota de qualidade.

5

Conclusão

Status alterado para concluido. O campo concluido_em é preenchido automaticamente. O custo total do chamado fica disponível no KPI do dashboard.

Módulo

Dashboard — Indicadores Gerenciais

Visão consolidada de performance em tempo real com filtros de período e status.

KPIs disponíveis (5 cards)

KPIFonte
Total de ChamadosGET /api/estatisticas/cards → total
Abertosstatus = aberto
Em Andamentostatus = em_andamento
Concluídosstatus = concluido
Custo Total (azul)SUM(tb_Horus_valor_chamado.valor_reais)

Gráficos

  • Distribuição por Urgência — gráfico de rosca (Chart.js)
  • Chamados por Departamento — gráfico de barras (Chart.js)

Filtros disponíveis

  • data_inicio / data_fim — filtra por criado_em
  • status — filtra por status específico
  • Todos os filtros são aplicados simultaneamente nos cards e nos gráficos
Módulo

Fila de Chamados

Gerenciamento e acompanhamento de todos os chamados abertos.

Funcionalidades

Status e cores

aberto em_andamento concluido cancelado

Urgência e cores

baixa media alta critica
Módulo · Fase 1

Valor do Chamado

Registro financeiro de custos por chamado — implementado na Fase 1.

Categorias de custo

EnumExibição
mao_de_obraMão de Obra
materialMaterial
equipamentoEquipamento
servico_terceiroServiço Terceiro
outrosOutros

Campos por item

  • categoria — enum obrigatório
  • valor_reais — NUMERIC(10,2) obrigatório
  • fornecedor_nome / fornecedor_contato — opcionais
  • nota_qualidade — 1 a 5 estrelas (opcional)
  • obs_qualidade — texto livre (opcional)
  • preenchido_por — email do usuário logado (automático)
check_circle
O custo total de todos os chamados é agregado no KPI "Custo Total" do Dashboard via SUM(valor_reais) no endpoint GET /api/estatisticas/cards.
Módulo

Administração

Gestão de usuários e auditoria de acesso — exclusivo para perfil admin.

Gestão de usuários

  • Criar novos usuários (email, senha, perfil)
  • Ativar / desativar usuário sem excluir
  • Redefinir senha pelo admin
  • Alterar perfil: adminanalista

Logs de acesso

  • Listagem de todos os eventos de sessão registrados em tb_Horus_logs
  • Visível apenas para administradores
  • Heartbeat atualiza ultimo_acesso a cada 10 segundos
API REST

Rotas da API

Documentação completa disponível em http://localhost:8000/docs (Swagger automático do FastAPI).

Autenticação · routers/auth.py
POST/api/loginAutentica e retorna token JWT + dados do usuário
GET/api/usuarios/{email}/statusHeartbeat — atualiza ultimo_acesso (a cada 10s)
PATCH/api/usuarios/{email}/senhaAltera própria senha (requer senha atual)
Chamados · routers/chamados.py
POST/api/chamadosCria chamado — multipart/form-data com anexo opcional. Sem autenticação (formulário público)
GET/api/chamadosLista todos os chamados ordenados pelo mais recente (requer JWT)
GET/api/chamados/{id}Retorna chamado com anexos, histórico e valores
PATCH/api/chamados/{id}Atualiza status e/ou responsável — registra no histórico automaticamente
POST/api/chamados/{id}/historicoAdiciona entrada manual ao histórico do chamado
Valor do Chamado · routers/valor.py
GET/api/chamados/{id}/valorLista itens de custo do chamado
POST/api/chamados/{id}/valorAdiciona item de custo (categoria, valor, fornecedor, nota)
DELETE/api/chamados/{id}/valor/{valor_id}Remove item de custo
Estatísticas · routers/estatisticas.py
GET/api/estatisticas/cardsKPIs: total, abertos, andamento, concluídos, custo_total. Aceita filtros data_inicio, data_fim, status
GET/api/estatisticas/graficosDados agregados por urgência e por departamento para os gráficos
Administração · routers/admin.py · Requer perfil admin
GET/api/admin/usuariosLista usuários (sem senha_hash)
POST/api/admin/usuariosCria novo usuário
PATCH/api/admin/usuarios/{email}/statusAtiva ou bloqueia usuário
PATCH/api/admin/usuarios/{email}/senhaRedefine senha (admin redefine para outro usuário)
GET/api/admin/logsLista logs de acesso de todos os usuários
Frontend

Frontend SPA

Single Page Application — arquivo único frontend/index.html com login overlay e 4 views.

Views e acesso

viewIdTítuloAcessoFunção de carga
viewInicioInícioTodosHub de navegação — sem carga de dados
viewDashboardIndicadores GerenciaisTodoscarregarDashboard()
viewChamadosFila de ChamadosTodoscarregarChamados()
viewAdminÁrea do AdministradorSomente admincarregarLogsAcesso() + carregarUsuariosADM()

Autenticação no frontend

ItemDetalhe
localStorage.getItem('omni_token')Token JWT Bearer — enviado em toda requisição autenticada via authFetch()
localStorage.getItem('calculadora_sessao')Objeto { email, perfil } — controla visibilidade de menus e rotas admin-only
authFetch(url, options)Wrapper de fetch() com Bearer automático. Intercepta 401 e chama fazerLogout()
iniciarGuardiao()Heartbeat a cada 10s em GET /api/usuarios/{email}/status
warning
Regra de display nas views: navegarPara() usa display: block por padrão. Views com classe .hub-container recebem display: flex (necessário para o layout centralizado do Hub). Se uma futura view precisar de flex, adicionar a detecção em auth.js:45.

Deploy Linux — única linha a alterar

/* No topo de frontend/index.html — alterar para o IP/domínio do servidor */ const API_BASE_URL = 'http://localhost:8000'; // ← alterar aqui
Referências

Regras Críticas

Pontos de atenção que previnem quebras no sistema.

block
form.html — NUNCA MODIFICAR. É o formulário público acessado via QR Code impresso fisicamente nos locais da empresa. Qualquer alteração quebra a experiência dos solicitantes sem login.
warning
Anaconda — sem venv local. Sempre executar com o python.exe do Anaconda diretamente. Nunca criar venv neste projeto.
info
create_all é seguro. models.Base.metadata.create_all() cria tabelas novas sem dropar as existentes. As tabelas tb_Horus_insumos e tb_Horus_insumos_movimento já existem no MySQL — não recriar manualmente.
info
CSS inline vs. layout.css. Estilos específicos de cada feature ficam no <style> do index.html. Design system global (sidebar, topbar, tabelas, KPIs) fica em css/layout.css.

Roadmap — Próximas Fases

FaseObjetivoStatus
Fase 0Unificação SPA — index.html, sidebar, hub, auth✅ Concluída
Fase 1Valor do Chamado — custos financeiros + KPI custo total✅ Concluída
Fase 2Insumos / Consumíveis — controle de estoque de materiais🔲 Pendente
Fase 3Data Base Viewer — visualização paginada das tabelas (admin)🔲 Pendente

Scripts auxiliares

# Criar/atualizar tabelas no banco python backend/init_db.py # Criar usuário admin inicial python backend/criar_admin.py # Gerar QR Code estático para impressão python gerar_qrcode.py