HEFESTO — Arquitetura Técnica
Sistema de Controle Orçamentário para Facilities
Versão: 1.0
Data: 2026-02-09
Stack: NestJS · React · PostgreSQL
1. Visão Geral da Arquitetura
2. Modelo de Dados Completo
2.1 Diagrama Entidade-Relacionamento (textual)
2.2 Tabelas
perfis
| Coluna |
Tipo |
Restrições |
| id |
UUID |
PK, DEFAULT gen_random_uuid() |
| nome |
VARCHAR(50) |
NOT NULL, UNIQUE |
| descricao |
TEXT |
|
| permissoes |
JSONB |
NOT NULL, DEFAULT '{}' |
| created_at |
TIMESTAMPTZ |
DEFAULT NOW() |
| updated_at |
TIMESTAMPTZ |
DEFAULT NOW() |
Valores seed: solicitante, gestor_facilities, aprovador_financeiro, diretoria, fornecedor, administrador
usuarios
| Coluna |
Tipo |
Restrições |
| id |
UUID |
PK |
| nome |
VARCHAR(200) |
NOT NULL |
| email |
VARCHAR(255) |
NOT NULL, UNIQUE |
| senha_hash |
VARCHAR(255) |
NOT NULL |
| perfil_id |
UUID |
FK → perfis.id, NOT NULL |
| ativo |
BOOLEAN |
DEFAULT TRUE |
| ultimo_acesso |
TIMESTAMPTZ |
|
| created_at |
TIMESTAMPTZ |
DEFAULT NOW() |
| updated_at |
TIMESTAMPTZ |
DEFAULT NOW() |
locais
| Coluna |
Tipo |
Restrições |
| id |
UUID |
PK |
| nome |
VARCHAR(200) |
NOT NULL |
| endereco |
TEXT |
|
| centro_custo_id |
UUID |
FK → centros_custo.id, NOT NULL |
| responsavel_id |
UUID |
FK → usuarios.id |
| ativo |
BOOLEAN |
DEFAULT TRUE |
| created_at |
TIMESTAMPTZ |
DEFAULT NOW() |
| updated_at |
TIMESTAMPTZ |
DEFAULT NOW() |
centros_custo
| Coluna |
Tipo |
Restrições |
| id |
UUID |
PK |
| codigo |
VARCHAR(20) |
NOT NULL, UNIQUE |
| nome |
VARCHAR(200) |
NOT NULL |
| responsavel_id |
UUID |
FK → usuarios.id |
| ativo |
BOOLEAN |
DEFAULT TRUE |
| created_at |
TIMESTAMPTZ |
DEFAULT NOW() |
| updated_at |
TIMESTAMPTZ |
DEFAULT NOW() |
categorias
| Coluna |
Tipo |
Restrições |
| id |
UUID |
PK |
| nome |
VARCHAR(200) |
NOT NULL |
| subcategoria |
VARCHAR(200) |
|
| criticidade_padrao |
VARCHAR(20) |
CHECK (criticidade_padrao IN ('baixa','media','alta','critica')) |
| sla_dias |
INTEGER |
DEFAULT 30 |
| categoria_pai_id |
UUID |
FK → categorias.id (auto-ref) |
| ativo |
BOOLEAN |
DEFAULT TRUE |
| created_at |
TIMESTAMPTZ |
DEFAULT NOW() |
| updated_at |
TIMESTAMPTZ |
DEFAULT NOW() |
fornecedores
| Coluna |
Tipo |
Restrições |
| id |
UUID |
PK |
| tipo_pessoa |
VARCHAR(10) |
NOT NULL, CHECK (tipo_pessoa IN ('PF','PJ')) |
| cpf_cnpj |
VARCHAR(18) |
NOT NULL, UNIQUE |
| razao_social |
VARCHAR(300) |
NOT NULL |
| nome_fantasia |
VARCHAR(300) |
|
| email |
VARCHAR(255) |
|
| telefone |
VARCHAR(20) |
|
| endereco |
TEXT |
|
| categorias_atendidas |
UUID[] |
(array de FK → categorias.id) |
| rating |
NUMERIC(2,1) |
DEFAULT 3.0, CHECK (rating >= 1 AND rating <= 5) |
| usuario_id |
UUID |
FK → usuarios.id (login do portal) |
| ativo |
BOOLEAN |
DEFAULT TRUE |
| created_at |
TIMESTAMPTZ |
DEFAULT NOW() |
| updated_at |
TIMESTAMPTZ |
DEFAULT NOW() |
certidoes
| Coluna |
Tipo |
Restrições |
| id |
UUID |
PK |
| fornecedor_id |
UUID |
FK → fornecedores.id, NOT NULL |
| tipo |
VARCHAR(100) |
NOT NULL |
| numero |
VARCHAR(100) |
|
| data_emissao |
DATE |
NOT NULL |
| data_validade |
DATE |
NOT NULL |
| arquivo_url |
TEXT |
|
| status |
VARCHAR(20) |
CHECK (status IN ('vigente','vencida','pendente')) |
| created_at |
TIMESTAMPTZ |
DEFAULT NOW() |
orcamento_planejado
| Coluna |
Tipo |
Restrições |
| id |
UUID |
PK |
| ano |
INTEGER |
NOT NULL |
| mes |
INTEGER |
NOT NULL, CHECK (mes BETWEEN 1 AND 12) |
| centro_custo_id |
UUID |
FK → centros_custo.id, NOT NULL |
| categoria_id |
UUID |
FK → categorias.id, NOT NULL |
| valor_planejado |
NUMERIC(15,2) |
NOT NULL |
| valor_comprometido |
NUMERIC(15,2) |
DEFAULT 0 |
| valor_realizado |
NUMERIC(15,2) |
DEFAULT 0 |
| created_at |
TIMESTAMPTZ |
DEFAULT NOW() |
| updated_at |
TIMESTAMPTZ |
DEFAULT NOW() |
| UNIQUE(ano, mes, centro_custo_id, categoria_id) |
|
|
demandas
| Coluna |
Tipo |
Restrições |
| id |
UUID |
PK |
| numero |
SERIAL |
UNIQUE (código sequencial) |
| titulo |
VARCHAR(300) |
NOT NULL |
| descricao |
TEXT |
|
| local_id |
UUID |
FK → locais.id, NOT NULL |
| centro_custo_id |
UUID |
FK → centros_custo.id, NOT NULL |
| categoria_id |
UUID |
FK → categorias.id, NOT NULL |
| criticidade |
VARCHAR(20) |
NOT NULL, CHECK (... IN ('baixa','media','alta','critica')) |
| data_desejada |
DATE |
|
| status |
VARCHAR(30) |
NOT NULL, DEFAULT 'rascunho' |
| solicitante_id |
UUID |
FK → usuarios.id, NOT NULL |
| gestor_id |
UUID |
FK → usuarios.id |
| documentos |
JSONB |
DEFAULT '[]' |
| created_at |
TIMESTAMPTZ |
DEFAULT NOW() |
| updated_at |
TIMESTAMPTZ |
DEFAULT NOW() |
Status possíveis: rascunho, aberta, em_escopo, em_cotacao, propostas_recebidas, em_comparacao, em_aprovacao, aprovada, os_emitida, em_execucao, concluida, cancelada
itens_linha
| Coluna |
Tipo |
Restrições |
| id |
UUID |
PK |
| demanda_id |
UUID |
FK → demandas.id, NOT NULL |
| descricao |
VARCHAR(300) |
NOT NULL |
| tipo |
VARCHAR(50) |
CHECK (tipo IN ('mao_de_obra','material','equipamento','outros')) |
| quantidade |
NUMERIC(10,2) |
|
| unidade |
VARCHAR(30) |
|
| observacoes |
TEXT |
|
| ordem |
INTEGER |
DEFAULT 0 |
| created_at |
TIMESTAMPTZ |
DEFAULT NOW() |
propostas
| Coluna |
Tipo |
Restrições |
| id |
UUID |
PK |
| demanda_id |
UUID |
FK → demandas.id, NOT NULL |
| fornecedor_id |
UUID |
FK → fornecedores.id, NOT NULL |
| versao_atual |
INTEGER |
DEFAULT 1 |
| valor_bruto |
NUMERIC(15,2) |
|
| valor_liquido |
NUMERIC(15,2) |
|
| impostos |
JSONB |
DEFAULT '{}' (iss, inss, pcc) |
| condicao_pagamento |
TEXT |
|
| prazo_execucao_dias |
INTEGER |
|
| data_entrega_estimada |
DATE |
|
| match_escopo_pct |
NUMERIC(5,2) |
|
| confiabilidade_ocr |
NUMERIC(5,2) |
|
| selecionada |
BOOLEAN |
DEFAULT FALSE |
| status |
VARCHAR(20) |
DEFAULT 'recebida' |
| created_at |
TIMESTAMPTZ |
DEFAULT NOW() |
| updated_at |
TIMESTAMPTZ |
DEFAULT NOW() |
versoes_proposta
| Coluna |
Tipo |
Restrições |
| id |
UUID |
PK |
| proposta_id |
UUID |
FK → propostas.id, NOT NULL |
| versao |
INTEGER |
NOT NULL |
| arquivo_url |
TEXT |
NOT NULL |
| arquivo_nome |
VARCHAR(300) |
|
| dados_extraidos |
JSONB |
(resultado bruto do OCR) |
| dados_parseados |
JSONB |
(resultado estruturado) |
| confiabilidade |
NUMERIC(5,2) |
|
| uploaded_by |
UUID |
FK → usuarios.id |
| created_at |
TIMESTAMPTZ |
DEFAULT NOW() |
comparativo_propostas
| Coluna |
Tipo |
Restrições |
| id |
UUID |
PK |
| demanda_id |
UUID |
FK → demandas.id, NOT NULL, UNIQUE |
| propostas_ids |
UUID[] |
NOT NULL |
| benchmark_id |
UUID |
FK → propostas.id |
| dados_comparativo |
JSONB |
NOT NULL |
| anotacoes |
JSONB |
DEFAULT '[]' |
| gerado_em |
TIMESTAMPTZ |
DEFAULT NOW() |
| atualizado_em |
TIMESTAMPTZ |
DEFAULT NOW() |
workflow_aprovacao
| Coluna |
Tipo |
Restrições |
| id |
UUID |
PK |
| demanda_id |
UUID |
FK → demandas.id, NOT NULL |
| proposta_id |
UUID |
FK → propostas.id, NOT NULL |
| valor_total |
NUMERIC(15,2) |
NOT NULL |
| status |
VARCHAR(30) |
NOT NULL, DEFAULT 'pendente' |
| etapa_atual |
INTEGER |
DEFAULT 1 |
| etapas |
JSONB |
NOT NULL (array de etapas) |
| emergencial |
BOOLEAN |
DEFAULT FALSE |
| justificativa_emergencial |
TEXT |
|
| created_at |
TIMESTAMPTZ |
DEFAULT NOW() |
| updated_at |
TIMESTAMPTZ |
DEFAULT NOW() |
Status: pendente, em_andamento, aprovado, reprovado, aprovado_com_ressalva, cancelado
Estrutura de etapas (JSONB):
matriz_alcada
| Coluna |
Tipo |
Restrições |
| id |
UUID |
PK |
| centro_custo_id |
UUID |
FK → centros_custo.id |
| valor_minimo |
NUMERIC(15,2) |
NOT NULL |
| valor_maximo |
NUMERIC(15,2) |
NOT NULL |
| perfil_aprovador |
VARCHAR(50) |
NOT NULL |
| ordem_sequencial |
INTEGER |
DEFAULT 1 |
| ativo |
BOOLEAN |
DEFAULT TRUE |
| created_at |
TIMESTAMPTZ |
DEFAULT NOW() |
ordens_servico
| Coluna |
Tipo |
Restrições |
| id |
UUID |
PK |
| numero |
SERIAL |
UNIQUE |
| demanda_id |
UUID |
FK → demandas.id, NOT NULL, UNIQUE |
| proposta_id |
UUID |
FK → propostas.id, NOT NULL |
| fornecedor_id |
UUID |
FK → fornecedores.id, NOT NULL |
| valor |
NUMERIC(15,2) |
NOT NULL |
| status |
VARCHAR(30) |
DEFAULT 'emitida' |
| data_emissao |
TIMESTAMPTZ |
DEFAULT NOW() |
| data_inicio |
DATE |
|
| data_conclusao |
DATE |
|
| observacoes |
TEXT |
|
| created_at |
TIMESTAMPTZ |
DEFAULT NOW() |
| updated_at |
TIMESTAMPTZ |
DEFAULT NOW() |
Status: emitida, em_execucao, concluida, cancelada
avaliacoes
| Coluna |
Tipo |
Restrições |
| id |
UUID |
PK |
| ordem_servico_id |
UUID |
FK → ordens_servico.id, NOT NULL, UNIQUE |
| fornecedor_id |
UUID |
FK → fornecedores.id, NOT NULL |
| avaliador_id |
UUID |
FK → usuarios.id, NOT NULL |
| nota |
NUMERIC(2,1) |
NOT NULL, CHECK (nota >= 1 AND nota <= 5) |
| comentario |
TEXT |
|
| created_at |
TIMESTAMPTZ |
DEFAULT NOW() |
audit_log
| Coluna |
Tipo |
Restrições |
| id |
UUID |
PK |
| usuario_id |
UUID |
FK → usuarios.id |
| acao |
VARCHAR(50) |
NOT NULL |
| entidade |
VARCHAR(50) |
NOT NULL |
| entidade_id |
UUID |
|
| dados_antes |
JSONB |
|
| dados_depois |
JSONB |
|
| ip |
VARCHAR(45) |
|
| user_agent |
TEXT |
|
| created_at |
TIMESTAMPTZ |
DEFAULT NOW() |
Índice: CREATE INDEX idx_audit_log_entidade ON audit_log(entidade, entidade_id);
Índice: CREATE INDEX idx_audit_log_usuario ON audit_log(usuario_id, created_at DESC);
alertas
| Coluna |
Tipo |
Restrições |
| id |
UUID |
PK |
| usuario_id |
UUID |
FK → usuarios.id, NOT NULL |
| tipo |
VARCHAR(50) |
NOT NULL |
| titulo |
VARCHAR(300) |
NOT NULL |
| mensagem |
TEXT |
|
| entidade |
VARCHAR(50) |
|
| entidade_id |
UUID |
|
| lido |
BOOLEAN |
DEFAULT FALSE |
| created_at |
TIMESTAMPTZ |
DEFAULT NOW() |
Tipos de alerta: estouro_orcamento, sla_vencendo, proposta_pendente, aprovacao_pendente, certidao_vencendo, os_atrasada
3. Módulos NestJS
3.1 Estrutura de Pastas
3.2 Dependências entre Módulos
4. API REST Completa
4.1 Autenticação (/api/auth)
| Método |
Rota |
Descrição |
Acesso |
| POST |
/api/auth/login |
Login (email + senha) → JWT |
Público |
| POST |
/api/auth/refresh |
Renovar token |
Autenticado |
| POST |
/api/auth/logout |
Invalidar refresh token |
Autenticado |
| GET |
/api/auth/me |
Dados do usuário logado |
Autenticado |
| POST |
/api/auth/forgot-password |
Solicitar reset de senha |
Público |
| POST |
/api/auth/reset-password |
Redefinir senha com token |
Público |
4.2 Usuários (/api/users)
| Método |
Rota |
Descrição |
Acesso |
| GET |
/api/users |
Listar usuários (paginado) |
Admin |
| GET |
/api/users/:id |
Detalhe do usuário |
Admin |
| POST |
/api/users |
Criar usuário |
Admin |
| PATCH |
/api/users/:id |
Atualizar usuário |
Admin |
| DELETE |
/api/users/:id |
Desativar usuário (soft) |
Admin |
| GET |
/api/perfis |
Listar perfis |
Admin |
| POST |
/api/perfis |
Criar perfil |
Admin |
| PATCH |
/api/perfis/:id |
Atualizar permissões |
Admin |
4.3 Locais e Centros de Custo (/api/locais, /api/centros-custo)
| Método |
Rota |
Descrição |
Acesso |
| GET |
/api/locais |
Listar locais |
Autenticado |
| GET |
/api/locais/:id |
Detalhe do local |
Autenticado |
| POST |
/api/locais |
Criar local |
Admin, Gestor |
| PATCH |
/api/locais/:id |
Atualizar local |
Admin, Gestor |
| DELETE |
/api/locais/:id |
Desativar local |
Admin |
| GET |
/api/centros-custo |
Listar centros de custo |
Autenticado |
| GET |
/api/centros-custo/:id |
Detalhe |
Autenticado |
| POST |
/api/centros-custo |
Criar CC |
Admin |
| PATCH |
/api/centros-custo/:id |
Atualizar CC |
Admin |
4.4 Categorias (/api/categorias)
| Método |
Rota |
Descrição |
Acesso |
| GET |
/api/categorias |
Listar (árvore ou flat) |
Autenticado |
| GET |
/api/categorias/:id |
Detalhe |
Autenticado |
| POST |
/api/categorias |
Criar categoria |
Admin |
| PATCH |
/api/categorias/:id |
Atualizar |
Admin |
| DELETE |
/api/categorias/:id |
Desativar |
Admin |
4.5 Fornecedores (/api/fornecedores)
| Método |
Rota |
Descrição |
Acesso |
| GET |
/api/fornecedores |
Listar (paginado, filtros) |
Autenticado |
| GET |
/api/fornecedores/:id |
Detalhe + certidões |
Autenticado |
| POST |
/api/fornecedores |
Cadastrar fornecedor |
Admin, Gestor |
| PATCH |
/api/fornecedores/:id |
Atualizar |
Admin, Gestor |
| DELETE |
/api/fornecedores/:id |
Desativar |
Admin |
| GET |
/api/fornecedores/:id/certidoes |
Listar certidões |
Autenticado |
| POST |
/api/fornecedores/:id/certidoes |
Upload certidão |
Fornecedor, Admin |
| PATCH |
/api/fornecedores/:id/certidoes/:certId |
Atualizar certidão |
Admin |
| GET |
/api/fornecedores/:id/avaliacoes |
Histórico de avaliações |
Autenticado |
4.6 Demandas (/api/demandas)
| Método |
Rota |
Descrição |
Acesso |
| GET |
/api/demandas |
Listar (paginado, filtros por status/CC/local/categoria) |
Autenticado |
| GET |
/api/demandas/:id |
Detalhe completo |
Autenticado |
| POST |
/api/demandas |
Criar demanda (rascunho) |
Solicitante, Gestor |
| PATCH |
/api/demandas/:id |
Atualizar demanda |
Solicitante, Gestor |
| POST |
/api/demandas/:id/publicar |
Publicar (rascunho → aberta) |
Solicitante, Gestor |
| POST |
/api/demandas/:id/cancelar |
Cancelar demanda |
Gestor, Admin |
| POST |
/api/demandas/:id/documentos |
Upload documento |
Solicitante, Gestor |
| DELETE |
/api/demandas/:id/documentos/:docId |
Remover documento |
Solicitante, Gestor |
| GET |
/api/demandas/:id/itens-linha |
Listar itens de linha |
Autenticado |
| POST |
/api/demandas/:id/itens-linha |
Adicionar item de linha |
Gestor |
| PATCH |
/api/demandas/:id/itens-linha/:itemId |
Atualizar item |
Gestor |
| DELETE |
/api/demandas/:id/itens-linha/:itemId |
Remover item |
Gestor |
| POST |
/api/demandas/:id/enviar-cotacao |
Enviar p/ cotação (validações) |
Gestor |
| GET |
/api/demandas/:id/timeline |
Timeline de eventos |
Autenticado |
4.7 Propostas (/api/propostas)
| Método |
Rota |
Descrição |
Acesso |
| GET |
/api/demandas/:demandaId/propostas |
Listar propostas da demanda |
Autenticado |
| GET |
/api/propostas/:id |
Detalhe da proposta |
Autenticado |
| POST |
/api/demandas/:demandaId/propostas |
Upload proposta (PDF) |
Fornecedor |
| POST |
/api/propostas/:id/nova-versao |
Nova versão do PDF |
Fornecedor |
| GET |
/api/propostas/:id/versoes |
Listar versões |
Autenticado |
| GET |
/api/propostas/:id/versoes/:versaoId |
Detalhe da versão + dados OCR |
Autenticado |
| POST |
/api/propostas/:id/selecionar |
Selecionar proposta vencedora |
Gestor |
| PATCH |
/api/propostas/:id/dados-extraidos |
Corrigir dados do OCR |
Gestor |
| GET |
/api/demandas/:demandaId/comparativo |
Painel comparativo |
Autenticado |
| POST |
/api/demandas/:demandaId/comparativo/gerar |
Gerar/atualizar comparativo |
Gestor |
| POST |
/api/demandas/:demandaId/comparativo/anotacoes |
Adicionar anotação |
Autenticado |
4.8 Orçamento (/api/orcamento)
| Método |
Rota |
Descrição |
Acesso |
| GET |
/api/orcamento |
Listar planejamento (filtros: ano, mês, CC, categoria) |
Financeiro, Admin |
| GET |
/api/orcamento/:id |
Detalhe |
Financeiro, Admin |
| POST |
/api/orcamento |
Criar linha orçamentária |
Admin |
| PATCH |
/api/orcamento/:id |
Atualizar planejado |
Admin |
| POST |
/api/orcamento/importar |
Importar planilha |
Admin |
| GET |
/api/orcamento/resumo |
Resumo planejado x comprometido x realizado |
Financeiro, Diretoria |
| GET |
/api/orcamento/verificar |
Verificar disponibilidade (CC, categoria, valor) |
Sistema |
4.9 Workflow de Aprovação (/api/workflow)
| Método |
Rota |
Descrição |
Acesso |
| POST |
/api/demandas/:demandaId/workflow/iniciar |
Iniciar workflow |
Gestor |
| GET |
/api/workflow/:id |
Status do workflow |
Autenticado |
| POST |
/api/workflow/:id/aprovar |
Aprovar etapa atual |
Aprovador da etapa |
| POST |
/api/workflow/:id/reprovar |
Reprovar (com justificativa) |
Aprovador da etapa |
| POST |
/api/workflow/:id/aprovar-com-ressalva |
Aprovar com ressalva |
Aprovador da etapa |
| GET |
/api/workflow/pendentes |
Minhas aprovações pendentes |
Autenticado |
| GET |
/api/matriz-alcada |
Listar regras de alçada |
Admin |
| POST |
/api/matriz-alcada |
Criar regra |
Admin |
| PATCH |
/api/matriz-alcada/:id |
Atualizar regra |
Admin |
| DELETE |
/api/matriz-alcada/:id |
Desativar regra |
Admin |
4.10 Ordens de Serviço (/api/ordens-servico)
| Método |
Rota |
Descrição |
Acesso |
| GET |
/api/ordens-servico |
Listar OS |
Autenticado |
| GET |
/api/ordens-servico/:id |
Detalhe |
Autenticado |
| POST |
/api/ordens-servico/:id/iniciar |
Marcar início execução |
Gestor |
| POST |
/api/ordens-servico/:id/concluir |
Marcar conclusão |
Gestor |
| POST |
/api/ordens-servico/:id/cancelar |
Cancelar OS |
Admin |
| POST |
/api/ordens-servico/:id/avaliacao |
Avaliar fornecedor |
Gestor, Solicitante |
4.11 Dashboard (/api/dashboard)
| Método |
Rota |
Descrição |
Acesso |
| GET |
/api/dashboard/indicadores |
Cards principais |
Autenticado |
| GET |
/api/dashboard/demandas-por-status |
Gráfico por status |
Autenticado |
| GET |
/api/dashboard/demandas-por-categoria |
Gráfico por categoria |
Autenticado |
| GET |
/api/dashboard/consumo-orcamento |
Plan. x Comprom. x Realiz. |
Financeiro, Diretoria |
| GET |
/api/dashboard/propostas-por-fornecedor |
Gráfico fornecedores |
Gestor |
| GET |
/api/dashboard/alertas |
Alertas do usuário |
Autenticado |
| PATCH |
/api/dashboard/alertas/:id/ler |
Marcar alerta como lido |
Autenticado |
4.12 Relatórios (/api/relatorios)
| Método |
Rota |
Descrição |
Acesso |
| GET |
/api/relatorios/consumo-orcamentario |
Por CC e categoria |
Financeiro, Diretoria |
| GET |
/api/relatorios/saving |
Saving gerado |
Financeiro, Diretoria |
| GET |
/api/relatorios/historico-decisoes |
Trilha de auditoria |
Admin |
| GET |
/api/relatorios/lead-time |
Lead time por status |
Gestor, Admin |
| GET |
/api/relatorios/gargalos |
Gargalos de aprovação |
Admin |
| GET |
/api/relatorios/exportar/:tipo |
Exportar PDF ou Excel |
Autenticado |
4.13 OCR (/api/ocr) — interno
| Método |
Rota |
Descrição |
Acesso |
| POST |
/api/ocr/extrair |
Disparar extração de PDF |
Sistema/Gestor |
| GET |
/api/ocr/status/:jobId |
Status do job de extração |
Sistema/Gestor |
5. Workflow de Aprovação — Máquina de Estados
5.1 Diagrama de Estados da Demanda
5.2 Fluxo de Alçadas (Workflow de Aprovação)
5.3 Exceções Emergenciais
- Demanda marcada como
criticidade = 'critica' pode ser sinalizada como emergencial
- Workflow emergencial exige
justificativa_emergencial obrigatória
- Permite pular etapas intermediárias, indo direto ao aprovador de maior alçada
- Gera alerta automático para todos os aprovadores pulados
- Registra em
audit_log com flag emergencial = true
5.4 Aprovação com Ressalva
- Qualquer aprovador pode aprovar com ressalva (
aprovado_com_ressalva)
- Exige campo
observacao obrigatório
- O workflow continua normalmente, mas a OS gerada carrega flag de ressalva
- Visível no relatório de histórico de decisões
6.1 Pipeline de Processamento
6.2 System Prompt para GPT-4o-mini
6.3 Match de Escopo
O serviço compara itens retornados pelo GPT com itens_linha da demanda usando similaridade textual (Levenshtein / embeddings simples). Resultado: match_escopo_pct na proposta.
6.4 Tratamento de Falhas
- Confiabilidade < 60%: alerta ao Gestor para revisão manual
- PDF escaneado com baixa qualidade: fallback para Tesseract + retry GPT
- Timeout GPT: retry com backoff exponencial (3 tentativas)
- Todos os erros logados em
audit_log
7. Segurança
7.1 RBAC — Controle de Acesso por Perfil
Matriz de Permissões:
| Recurso |
Solicitante |
Gestor |
Financeiro |
Diretoria |
Fornecedor |
Admin |
| Criar demanda |
✅ |
✅ |
❌ |
❌ |
❌ |
✅ |
| Definir escopo |
❌ |
✅ |
❌ |
❌ |
❌ |
✅ |
| Upload proposta |
❌ |
❌ |
❌ |
❌ |
✅ |
✅ |
| Comparar propostas |
❌ |
✅ |
✅ |
✅ |
❌ |
✅ |
| Selecionar proposta |
❌ |
✅ |
❌ |
❌ |
❌ |
✅ |
| Aprovar workflow |
❌ |
✅ |
✅ |
✅ |
❌ |
❌ |
| Ver orçamento |
❌ |
✅ |
✅ |
✅ |
❌ |
✅ |
| Editar orçamento |
❌ |
❌ |
❌ |
❌ |
❌ |
✅ |
| Cadastros base |
❌ |
❌ |
❌ |
❌ |
❌ |
✅ |
| Relatórios |
❌ |
✅ |
✅ |
✅ |
❌ |
✅ |
| Avaliar fornecedor |
✅ |
✅ |
❌ |
❌ |
❌ |
✅ |
7.2 Autenticação
- JWT com access token (15 min) + refresh token (7 dias)
- Refresh tokens armazenados em banco (revogáveis)
- Bcrypt para hash de senhas (salt rounds: 12)
- Rate limiting: 5 tentativas de login / 15 min por IP
7.3 LGPD
- Dados pessoais de fornecedores (CPF/CNPJ) criptografados em repouso (AES-256)
- Endpoint
DELETE /api/users/:id/dados-pessoais para anonimização
- Consentimento registrado no cadastro de fornecedores
- Logs de acesso a dados sensíveis em
audit_log
- Retenção de logs: 5 anos (configurável)
7.4 Audit Log
Todo CUD (Create, Update, Delete) é interceptado pelo AuditInterceptor:
8. Infraestrutura e Deploy
8.1 Ambientes
| Ambiente |
Descrição |
development |
Local, Docker Compose |
staging |
Pré-produção |
production |
Produção |
8.2 Docker Compose (dev)
8.3 Tecnologias e Bibliotecas
| Camada |
Tecnologia |
| Backend |
NestJS 10+, TypeScript 5+ |
| ORM |
TypeORM (migrations + entities) |
| Validação |
class-validator, class-transformer |
| Filas |
BullMQ + Redis |
| Autenticação |
@nestjs/passport, passport-jwt |
| Upload |
Multer + S3 SDK |
| PDF parse |
pdf-parse, Tesseract.js |
| IA |
OpenAI SDK (GPT-4o-mini) |
| Frontend |
React 18+, Vite 5+ |
| UI Kit |
shadcn/ui + Tailwind CSS |
| State |
TanStack Query (React Query) |
| Gráficos |
Recharts |
| Tabelas |
TanStack Table |
| Exportação |
jsPDF, ExcelJS |
| Testes |
Jest (back), Vitest (front) |
9. Índices do Banco de Dados
10. Regras de Negócio Críticas
- Demanda sem itens de linha não pode ser publicada — validação no
POST /demandas/:id/publicar
- Demanda sem CC e Local não pode ser publicada — validação no
POST /demandas/:id/publicar
- Fornecedor com certidão vencida não pode receber OS — verificação no momento da geração da OS
- Alerta automático quando proposta > 20% do orçamento planejado — trigger no
OrcamentoService.verificar()
- OS gerada automaticamente após aprovação final — event listener no
WorkflowService
- Rating do fornecedor atualizado após avaliação — média ponderada recalculada
- Valor comprometido atualizado ao emitir OS —
OrcamentoService.comprometer()
- Valor realizado atualizado ao concluir OS —
OrcamentoService.realizar()
- Soft delete em todas as entidades cadastrais — campo
ativo ao invés de DELETE físico
Documento gerado para o projeto HEFESTO — v1.0