2194 lines
54 KiB
HTML
2194 lines
54 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="pt-BR">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>HEFESTO - Manual Técnico</title>
|
||
<style>
|
||
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800;900&display=swap');
|
||
|
||
@page {
|
||
size: A4;
|
||
margin: 2cm 2cm 2.5cm 2cm;
|
||
@top-center {
|
||
content: "";
|
||
}
|
||
@bottom-center {
|
||
content: counter(page);
|
||
font-family: 'Inter', 'Segoe UI', sans-serif;
|
||
font-size: 9pt;
|
||
color: #999;
|
||
}
|
||
}
|
||
|
||
@page :first {
|
||
margin: 0;
|
||
@bottom-center { content: ""; }
|
||
}
|
||
|
||
* { box-sizing: border-box; }
|
||
|
||
body {
|
||
font-family: 'Inter', 'Segoe UI', 'Helvetica Neue', Arial, sans-serif;
|
||
font-size: 10.5pt;
|
||
line-height: 1.7;
|
||
color: #333;
|
||
-webkit-print-color-adjust: exact !important;
|
||
print-color-adjust: exact !important;
|
||
}
|
||
|
||
/* COVER PAGE */
|
||
.cover {
|
||
page-break-after: always;
|
||
width: 210mm;
|
||
height: 297mm;
|
||
margin: -2cm;
|
||
padding: 0;
|
||
display: flex;
|
||
flex-direction: column;
|
||
justify-content: center;
|
||
align-items: center;
|
||
background: linear-gradient(160deg, #0D1B2A 0%, #1A237E 40%, #1A237E 60%, #0D1B2A 100%);
|
||
color: white;
|
||
text-align: center;
|
||
position: relative;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.cover::before {
|
||
content: '';
|
||
position: absolute;
|
||
top: 0;
|
||
left: 0;
|
||
right: 0;
|
||
height: 8px;
|
||
background: linear-gradient(90deg, #E65100, #FF8F00, #FFB300);
|
||
}
|
||
|
||
.cover::after {
|
||
content: '';
|
||
position: absolute;
|
||
bottom: 0;
|
||
left: 0;
|
||
right: 0;
|
||
height: 8px;
|
||
background: linear-gradient(90deg, #FFB300, #FF8F00, #E65100);
|
||
}
|
||
|
||
.cover .logo-icon {
|
||
font-size: 80pt;
|
||
margin-bottom: 10px;
|
||
filter: drop-shadow(0 4px 20px rgba(255, 143, 0, 0.5));
|
||
}
|
||
|
||
.cover .brand {
|
||
font-size: 42pt;
|
||
font-weight: 900;
|
||
letter-spacing: 12px;
|
||
margin-bottom: 5px;
|
||
background: linear-gradient(90deg, #FF8F00, #FFB300);
|
||
-webkit-background-clip: text;
|
||
-webkit-text-fill-color: transparent;
|
||
}
|
||
|
||
.cover .divider {
|
||
width: 120px;
|
||
height: 3px;
|
||
background: linear-gradient(90deg, transparent, #FF8F00, transparent);
|
||
margin: 20px auto;
|
||
}
|
||
|
||
.cover .manual-title {
|
||
font-size: 22pt;
|
||
font-weight: 300;
|
||
letter-spacing: 3px;
|
||
text-transform: uppercase;
|
||
color: rgba(255,255,255,0.95);
|
||
margin-bottom: 8px;
|
||
}
|
||
|
||
.cover .manual-subtitle {
|
||
font-size: 12pt;
|
||
font-weight: 300;
|
||
color: rgba(255,255,255,0.6);
|
||
margin-bottom: 60px;
|
||
}
|
||
|
||
.cover .meta {
|
||
position: absolute;
|
||
bottom: 50px;
|
||
text-align: center;
|
||
width: 100%;
|
||
}
|
||
|
||
.cover .company {
|
||
font-size: 11pt;
|
||
font-weight: 500;
|
||
letter-spacing: 4px;
|
||
text-transform: uppercase;
|
||
color: rgba(255,255,255,0.5);
|
||
margin-bottom: 8px;
|
||
}
|
||
|
||
.cover .date {
|
||
font-size: 10pt;
|
||
color: rgba(255,255,255,0.35);
|
||
letter-spacing: 2px;
|
||
}
|
||
|
||
/* GEOMETRIC DECORATIONS */
|
||
.cover .geo1 {
|
||
position: absolute;
|
||
top: 60px;
|
||
right: 60px;
|
||
width: 200px;
|
||
height: 200px;
|
||
border: 1px solid rgba(255,143,0,0.15);
|
||
border-radius: 50%;
|
||
}
|
||
|
||
.cover .geo2 {
|
||
position: absolute;
|
||
bottom: 120px;
|
||
left: 40px;
|
||
width: 150px;
|
||
height: 150px;
|
||
border: 1px solid rgba(255,143,0,0.1);
|
||
transform: rotate(45deg);
|
||
}
|
||
|
||
/* PAGE HEADER */
|
||
.page-header {
|
||
page-break-after: avoid;
|
||
margin-bottom: 30px;
|
||
padding-bottom: 12px;
|
||
border-bottom: 2px solid #E65100;
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
font-size: 9pt;
|
||
color: #999;
|
||
letter-spacing: 2px;
|
||
text-transform: uppercase;
|
||
}
|
||
|
||
.page-header .left {
|
||
font-weight: 700;
|
||
color: #1A237E;
|
||
}
|
||
|
||
.page-header .right {
|
||
color: #E65100;
|
||
}
|
||
|
||
/* TABLE OF CONTENTS */
|
||
.toc-page {
|
||
page-break-after: always;
|
||
}
|
||
|
||
.toc-page h2 {
|
||
font-size: 18pt;
|
||
color: #1A237E;
|
||
border: none;
|
||
padding: 0;
|
||
margin-bottom: 25px;
|
||
letter-spacing: 3px;
|
||
text-transform: uppercase;
|
||
}
|
||
|
||
.toc-page h2::before {
|
||
content: '';
|
||
display: block;
|
||
width: 50px;
|
||
height: 3px;
|
||
background: #E65100;
|
||
margin-bottom: 15px;
|
||
}
|
||
|
||
/* HEADINGS */
|
||
h1 {
|
||
font-size: 22pt;
|
||
font-weight: 800;
|
||
color: #1A237E;
|
||
margin-top: 40px;
|
||
margin-bottom: 20px;
|
||
padding-bottom: 10px;
|
||
border-bottom: 3px solid #E65100;
|
||
page-break-after: avoid;
|
||
letter-spacing: -0.5px;
|
||
}
|
||
|
||
h2 {
|
||
font-size: 16pt;
|
||
font-weight: 700;
|
||
color: #1A237E;
|
||
margin-top: 35px;
|
||
margin-bottom: 15px;
|
||
padding-left: 15px;
|
||
border-left: 4px solid #E65100;
|
||
page-break-after: avoid;
|
||
}
|
||
|
||
h3 {
|
||
font-size: 13pt;
|
||
font-weight: 600;
|
||
color: #283593;
|
||
margin-top: 25px;
|
||
margin-bottom: 12px;
|
||
page-break-after: avoid;
|
||
}
|
||
|
||
h4 {
|
||
font-size: 11pt;
|
||
font-weight: 600;
|
||
color: #E65100;
|
||
margin-top: 20px;
|
||
margin-bottom: 10px;
|
||
text-transform: uppercase;
|
||
letter-spacing: 1px;
|
||
}
|
||
|
||
/* FIRST H1 — remove top margin after cover */
|
||
.content > h1:first-child {
|
||
margin-top: 0;
|
||
}
|
||
|
||
/* PARAGRAPHS */
|
||
p {
|
||
margin-bottom: 12px;
|
||
text-align: justify;
|
||
hyphens: auto;
|
||
}
|
||
|
||
/* STRONG/BOLD in special contexts */
|
||
strong {
|
||
color: #1A237E;
|
||
font-weight: 600;
|
||
}
|
||
|
||
/* TABLES */
|
||
table {
|
||
width: 100%;
|
||
border-collapse: collapse;
|
||
margin: 20px 0;
|
||
font-size: 9.5pt;
|
||
page-break-inside: avoid;
|
||
box-shadow: 0 1px 4px rgba(0,0,0,0.08);
|
||
border-radius: 6px;
|
||
overflow: hidden;
|
||
}
|
||
|
||
thead {
|
||
background: linear-gradient(135deg, #1A237E, #283593);
|
||
}
|
||
|
||
th {
|
||
color: white;
|
||
font-weight: 600;
|
||
text-align: left;
|
||
padding: 12px 14px;
|
||
font-size: 9pt;
|
||
text-transform: uppercase;
|
||
letter-spacing: 0.5px;
|
||
}
|
||
|
||
td {
|
||
padding: 10px 14px;
|
||
border-bottom: 1px solid #E8EAF6;
|
||
vertical-align: top;
|
||
}
|
||
|
||
tbody tr:nth-child(even) {
|
||
background-color: #F5F5FF;
|
||
}
|
||
|
||
tbody tr:hover {
|
||
background-color: #E8EAF6;
|
||
}
|
||
|
||
/* Checkmark styling for comparison tables */
|
||
td:has(text("✅")), td:has(text("❌")) {
|
||
text-align: center;
|
||
font-size: 14pt;
|
||
}
|
||
|
||
/* CODE BLOCKS */
|
||
pre {
|
||
background: #1E1E2E;
|
||
color: #CDD6F4;
|
||
border-radius: 8px;
|
||
padding: 18px 20px;
|
||
font-size: 9pt;
|
||
line-height: 1.6;
|
||
overflow-x: auto;
|
||
margin: 18px 0;
|
||
page-break-inside: avoid;
|
||
border-left: 4px solid #E65100;
|
||
}
|
||
|
||
code {
|
||
font-family: 'JetBrains Mono', 'Fira Code', 'Consolas', monospace;
|
||
font-size: 9pt;
|
||
}
|
||
|
||
p code, li code, td code {
|
||
background: #EDE7F6;
|
||
color: #4A148C;
|
||
padding: 2px 7px;
|
||
border-radius: 4px;
|
||
font-size: 8.5pt;
|
||
}
|
||
|
||
/* LISTS */
|
||
ul, ol {
|
||
margin: 10px 0;
|
||
padding-left: 24px;
|
||
}
|
||
|
||
li {
|
||
margin-bottom: 6px;
|
||
line-height: 1.6;
|
||
}
|
||
|
||
li::marker {
|
||
color: #E65100;
|
||
font-weight: bold;
|
||
}
|
||
|
||
/* BLOCKQUOTES / CALLOUTS */
|
||
blockquote {
|
||
background: linear-gradient(135deg, #FFF3E0, #FFF8E1);
|
||
border-left: 4px solid #FF8F00;
|
||
margin: 20px 0;
|
||
padding: 16px 20px;
|
||
border-radius: 0 8px 8px 0;
|
||
font-style: normal;
|
||
page-break-inside: avoid;
|
||
}
|
||
|
||
blockquote p {
|
||
margin: 0;
|
||
color: #5D4037;
|
||
}
|
||
|
||
blockquote strong {
|
||
color: #E65100;
|
||
}
|
||
|
||
/* HORIZONTAL RULES */
|
||
hr {
|
||
border: none;
|
||
height: 2px;
|
||
background: linear-gradient(90deg, #E65100, #FF8F00, transparent);
|
||
margin: 35px 0;
|
||
}
|
||
|
||
/* LINKS */
|
||
a {
|
||
color: #1A237E;
|
||
text-decoration: none;
|
||
border-bottom: 1px solid #E65100;
|
||
}
|
||
|
||
/* INFO BOX */
|
||
.info-box {
|
||
background: #E3F2FD;
|
||
border-left: 4px solid #1565C0;
|
||
padding: 14px 18px;
|
||
border-radius: 0 8px 8px 0;
|
||
margin: 18px 0;
|
||
}
|
||
|
||
/* SUCCESS BOX */
|
||
.success-box {
|
||
background: #E8F5E9;
|
||
border-left: 4px solid #2E7D32;
|
||
padding: 14px 18px;
|
||
border-radius: 0 8px 8px 0;
|
||
margin: 18px 0;
|
||
}
|
||
|
||
/* WARNING BOX */
|
||
.warning-box {
|
||
background: #FFF3E0;
|
||
border-left: 4px solid #E65100;
|
||
padding: 14px 18px;
|
||
border-radius: 0 8px 8px 0;
|
||
margin: 18px 0;
|
||
}
|
||
|
||
/* PAGE BREAKS for major sections */
|
||
h1 {
|
||
page-break-before: always;
|
||
}
|
||
|
||
h1:first-of-type {
|
||
page-break-before: avoid;
|
||
}
|
||
|
||
/* FOOTER NOTE */
|
||
.doc-footer {
|
||
margin-top: 40px;
|
||
padding-top: 15px;
|
||
border-top: 1px solid #E0E0E0;
|
||
text-align: center;
|
||
font-size: 8.5pt;
|
||
color: #999;
|
||
font-style: italic;
|
||
}
|
||
|
||
/* Emoji sizing */
|
||
.emoji-icon {
|
||
font-size: 14pt;
|
||
}
|
||
|
||
/* Print optimizations */
|
||
@media print {
|
||
body { -webkit-print-color-adjust: exact !important; }
|
||
.cover { page-break-after: always; }
|
||
h1, h2, h3 { page-break-after: avoid; }
|
||
table, pre, blockquote { page-break-inside: avoid; }
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
|
||
<div class="cover">
|
||
<div class="geo1"></div>
|
||
<div class="geo2"></div>
|
||
<div class="logo-icon">🔥</div>
|
||
<div class="brand">HEFESTO</div>
|
||
<div class="divider"></div>
|
||
<div class="manual-title">Manual Técnico</div>
|
||
<div class="manual-subtitle">Documentação Técnica Completa</div>
|
||
<div class="meta">
|
||
<div class="company">Kislanski Industries | AI Vertice</div>
|
||
<div class="date">Fevereiro 2026 · v2.0</div>
|
||
</div>
|
||
</div>
|
||
|
||
|
||
<div class="toc-page">
|
||
<h2>Sumário</h2>
|
||
<div class="toc">
|
||
<ul>
|
||
<li><a href="#hefesto-manual-tecnico">HEFESTO — Manual Técnico</a><ul>
|
||
<li><a href="#1-visao-geral-da-arquitetura">1. Visão Geral da Arquitetura</a></li>
|
||
<li><a href="#2-stack-completa">2. Stack Completa</a></li>
|
||
<li><a href="#3-estrutura-de-pastas">3. Estrutura de Pastas</a><ul>
|
||
<li><a href="#31-backend">3.1 Backend</a></li>
|
||
<li><a href="#32-frontend">3.2 Frontend</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a href="#4-modelo-de-dados">4. Modelo de Dados</a><ul>
|
||
<li><a href="#41-diagrama-de-entidades">4.1 Diagrama de Entidades</a></li>
|
||
<li><a href="#42-descricao-das-entidades">4.2 Descrição das Entidades</a></li>
|
||
<li><a href="#43-perfis-de-acesso-rbac">4.3 Perfis de Acesso (RBAC)</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a href="#5-api-endpoints">5. API — Endpoints</a><ul>
|
||
<li><a href="#51-autenticacao-apiauth">5.1 Autenticação (/api/auth)</a></li>
|
||
<li><a href="#52-usuarios-apiusers">5.2 Usuários (/api/users)</a></li>
|
||
<li><a href="#53-locais-apilocais">5.3 Locais (/api/locais)</a></li>
|
||
<li><a href="#54-centros-de-custo-apicentros-custo">5.4 Centros de Custo (/api/centros-custo)</a></li>
|
||
<li><a href="#55-categorias-apicategorias">5.5 Categorias (/api/categorias)</a></li>
|
||
<li><a href="#56-fornecedores-apifornecedores">5.6 Fornecedores (/api/fornecedores)</a></li>
|
||
<li><a href="#57-demandas-apidemandas">5.7 Demandas (/api/demandas)</a></li>
|
||
<li><a href="#58-propostas-apipropostas">5.8 Propostas (/api/propostas)</a></li>
|
||
<li><a href="#59-orcamento-apiorcamento">5.9 Orçamento (/api/orcamento)</a></li>
|
||
<li><a href="#510-workflow-apiworkflow">5.10 Workflow (/api/workflow)</a></li>
|
||
<li><a href="#511-dashboard-apidashboard">5.11 Dashboard (/api/dashboard)</a></li>
|
||
<li><a href="#512-ordens-de-servico-apiordens-servico">5.12 Ordens de Serviço (/api/ordens-servico)</a></li>
|
||
<li><a href="#513-alertas-apialertas">5.13 Alertas (/api/alertas)</a></li>
|
||
<li><a href="#514-esg-sustentabilidade-apiesg">5.14 ESG / Sustentabilidade (/api/esg)</a></li>
|
||
<li><a href="#515-kpis-indicadores-de-performance-apikpis">5.15 KPIs — Indicadores de Performance (/api/kpis)</a></li>
|
||
<li><a href="#516-auditoria-e-compliance-apiaudit">5.16 Auditoria e Compliance (/api/audit)</a></li>
|
||
<li><a href="#517-importacao-de-dados-apiimport">5.17 Importação de Dados (/api/import)</a></li>
|
||
<li><a href="#518-relatorios-automatizados-apirelatorios">5.18 Relatórios Automatizados (/api/relatorios)</a></li>
|
||
<li><a href="#519-metas-e-progresso-apimetas">5.19 Metas e Progresso (/api/metas)</a></li>
|
||
<li><a href="#520-alertas-inteligentes-apialertas">5.20 Alertas Inteligentes (/api/alertas)</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a href="#6-autenticacao-e-autorizacao">6. Autenticação e Autorização</a><ul>
|
||
<li><a href="#61-fluxo-jwt">6.1 Fluxo JWT</a></li>
|
||
<li><a href="#62-guards-nestjs">6.2 Guards NestJS</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a href="#7-workflow-de-aprovacao">7. Workflow de Aprovação</a><ul>
|
||
<li><a href="#71-maquina-de-estados">7.1 Máquina de Estados</a></li>
|
||
<li><a href="#72-alcadas-de-aprovacao">7.2 Alçadas de Aprovação</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a href="#8-como-rodar-localmente">8. Como Rodar Localmente</a><ul>
|
||
<li><a href="#81-pre-requisitos">8.1 Pré-requisitos</a></li>
|
||
<li><a href="#82-backend">8.2 Backend</a></li>
|
||
<li><a href="#83-frontend">8.3 Frontend</a></li>
|
||
<li><a href="#84-acesso-inicial">8.4 Acesso Inicial</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a href="#9-deploy-em-producao">9. Deploy em Produção</a><ul>
|
||
<li><a href="#91-infraestrutura">9.1 Infraestrutura</a></li>
|
||
<li><a href="#92-nginx-config">9.2 Nginx Config</a></li>
|
||
<li><a href="#93-pm2">9.3 PM2</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a href="#10-variaveis-de-ambiente">10. Variáveis de Ambiente</a><ul>
|
||
<li><a href="#backend-env">Backend (.env)</a></li>
|
||
<li><a href="#frontend-env">Frontend (.env)</a></li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
</div>
|
||
|
||
</div>
|
||
|
||
<div class="page-header">
|
||
<span class="left">HEFESTO — Manual Técnico</span>
|
||
<span class="right">v2.0</span>
|
||
</div>
|
||
|
||
<div class="content">
|
||
<h1 id="hefesto-manual-tecnico">HEFESTO — Manual Técnico</h1>
|
||
<p><strong>Sistema de Controle Orçamentário para Facilities</strong></p>
|
||
<p>Versão 2.0 | Fevereiro 2025</p>
|
||
<hr />
|
||
<h2 id="1-visao-geral-da-arquitetura">1. Visão Geral da Arquitetura</h2>
|
||
<p>O HEFESTO é uma aplicação web fullstack composta por:</p>
|
||
<ul>
|
||
<li><strong>Backend:</strong> API REST em NestJS (Node.js) com TypeORM</li>
|
||
<li><strong>Frontend:</strong> SPA em React + TypeScript com Vite</li>
|
||
<li><strong>Banco de Dados:</strong> SQLite (desenvolvimento) / PostgreSQL (produção)</li>
|
||
<li><strong>Autenticação:</strong> JWT com RBAC (Role-Based Access Control)</li>
|
||
</ul>
|
||
<pre><code>┌─────────────────┐ HTTP/REST ┌─────────────────┐
|
||
│ React SPA │ ◄──────────────► │ NestJS API │
|
||
│ (Vite) │ JWT Bearer │ (TypeORM) │
|
||
│ Port 5173 │ │ Port 3000 │
|
||
└─────────────────┘ └────────┬────────┘
|
||
│
|
||
┌────────▼────────┐
|
||
│ SQLite / PG │
|
||
└─────────────────┘
|
||
</code></pre>
|
||
<h2 id="2-stack-completa">2. Stack Completa</h2>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Componente</th>
|
||
<th>Tecnologia</th>
|
||
<th>Versão</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>Runtime</td>
|
||
<td>Node.js</td>
|
||
<td>22.x LTS</td>
|
||
</tr>
|
||
<tr>
|
||
<td>Backend Framework</td>
|
||
<td>NestJS</td>
|
||
<td>10.x</td>
|
||
</tr>
|
||
<tr>
|
||
<td>ORM</td>
|
||
<td>TypeORM</td>
|
||
<td>0.3.x</td>
|
||
</tr>
|
||
<tr>
|
||
<td>Frontend Framework</td>
|
||
<td>React</td>
|
||
<td>18.x</td>
|
||
</tr>
|
||
<tr>
|
||
<td>Build Tool</td>
|
||
<td>Vite</td>
|
||
<td>5.x</td>
|
||
</tr>
|
||
<tr>
|
||
<td>Linguagem</td>
|
||
<td>TypeScript</td>
|
||
<td>5.x</td>
|
||
</tr>
|
||
<tr>
|
||
<td>UI Components</td>
|
||
<td>Tailwind CSS</td>
|
||
<td>3.x</td>
|
||
</tr>
|
||
<tr>
|
||
<td>BD Desenvolvimento</td>
|
||
<td>SQLite3</td>
|
||
<td>5.x</td>
|
||
</tr>
|
||
<tr>
|
||
<td>BD Produção</td>
|
||
<td>PostgreSQL</td>
|
||
<td>16.x</td>
|
||
</tr>
|
||
<tr>
|
||
<td>Auth</td>
|
||
<td>@nestjs/jwt + passport</td>
|
||
<td>10.x</td>
|
||
</tr>
|
||
<tr>
|
||
<td>HTTP Client</td>
|
||
<td>Axios</td>
|
||
<td>1.x</td>
|
||
</tr>
|
||
<tr>
|
||
<td>Validação</td>
|
||
<td>class-validator</td>
|
||
<td>0.14.x</td>
|
||
</tr>
|
||
<tr>
|
||
<td>Documentação API</td>
|
||
<td>@nestjs/swagger</td>
|
||
<td>7.x</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h2 id="3-estrutura-de-pastas">3. Estrutura de Pastas</h2>
|
||
<h3 id="31-backend">3.1 Backend</h3>
|
||
<pre><code>backend/
|
||
├── src/
|
||
│ ├── main.ts # Bootstrap da aplicação
|
||
│ ├── app.module.ts # Módulo raiz
|
||
│ ├── common/ # Guards, decorators, pipes, interceptors
|
||
│ │ ├── guards/
|
||
│ │ │ ├── jwt-auth.guard.ts
|
||
│ │ │ └── roles.guard.ts
|
||
│ │ ├── decorators/
|
||
│ │ │ ├── roles.decorator.ts
|
||
│ │ │ └── current-user.decorator.ts
|
||
│ │ └── interceptors/
|
||
│ │ └── audit.interceptor.ts
|
||
│ ├── database/ # Configuração TypeORM, migrations, seeds
|
||
│ │ ├── database.module.ts
|
||
│ │ ├── migrations/
|
||
│ │ └── seeds/
|
||
│ └── modules/
|
||
│ ├── auth/ # Autenticação JWT, login, refresh token
|
||
│ │ ├── auth.controller.ts
|
||
│ │ ├── auth.service.ts
|
||
│ │ ├── auth.module.ts
|
||
│ │ ├── strategies/
|
||
│ │ │ └── jwt.strategy.ts
|
||
│ │ └── dto/
|
||
│ ├── users/ # CRUD de usuários e perfis
|
||
│ │ ├── users.controller.ts
|
||
│ │ ├── users.service.ts
|
||
│ │ ├── entities/
|
||
│ │ │ ├── usuario.entity.ts
|
||
│ │ │ └── perfil.entity.ts
|
||
│ │ └── dto/
|
||
│ ├── locais/ # Gestão de locais/unidades
|
||
│ ├── centros-custo/ # Centros de custo vinculados a locais
|
||
│ ├── categorias/ # Categorias de serviço
|
||
│ ├── fornecedores/ # Cadastro de fornecedores e certidões
|
||
│ ├── demandas/ # Abertura e gestão de demandas
|
||
│ ├── propostas/ # Recebimento e comparação de propostas
|
||
│ ├── orcamento/ # Orçamento planejado vs realizado
|
||
│ ├── workflow/ # Máquina de estados de aprovação
|
||
│ ├── dashboard/ # Indicadores e relatórios
|
||
│ ├── ordens-servico/ # Emissão e acompanhamento de OS
|
||
│ ├── esg/ # Métricas ESG e sustentabilidade
|
||
│ ├── kpis/ # Indicadores de performance
|
||
│ ├── audit/ # Auditoria e compliance avançado
|
||
│ ├── import/ # Importação de dados Excel/CSV
|
||
│ ├── relatorios/ # Relatórios automatizados
|
||
│ ├── metas/ # Metas e acompanhamento de progresso
|
||
│ └── alertas-inteligentes/ # Configuração e verificação de alertas
|
||
├── test/
|
||
├── nest-cli.json
|
||
├── tsconfig.json
|
||
└── package.json
|
||
</code></pre>
|
||
<h3 id="32-frontend">3.2 Frontend</h3>
|
||
<pre><code>frontend/
|
||
├── src/
|
||
│ ├── main.tsx # Entry point
|
||
│ ├── App.tsx # Router + Layout
|
||
│ ├── assets/ # Imagens, ícones
|
||
│ ├── components/ # Componentes reutilizáveis
|
||
│ │ ├── Layout/
|
||
│ │ ├── Sidebar/
|
||
│ │ ├── Header/
|
||
│ │ ├── DataTable/
|
||
│ │ ├── StatusBadge/
|
||
│ │ └── Charts/
|
||
│ ├── pages/
|
||
│ │ ├── Login.tsx # Tela de autenticação
|
||
│ │ ├── Dashboard.tsx # Painel de indicadores
|
||
│ │ ├── Demandas.tsx # Lista de demandas com filtros
|
||
│ │ ├── Landing.tsx # Página inicial / nova demanda
|
||
│ │ ├── Fornecedores.tsx # Gestão de fornecedores
|
||
│ │ ├── Orcamentos.tsx # Orçamento planejado vs realizado
|
||
│ │ ├── OrdensServico.tsx # Ordens de serviço
|
||
│ │ ├── Relatorios.tsx # Relatórios gerenciais
|
||
│ │ ├── Usuarios.tsx # Administração de usuários
|
||
│ │ ├── ESG.tsx # Dashboard ESG e métricas ambientais
|
||
│ │ ├── KPIs.tsx # Painel de indicadores de performance
|
||
│ │ ├── Auditoria.tsx # Logs de auditoria e compliance
|
||
│ │ ├── Importacao.tsx # Upload de planilhas Excel/CSV
|
||
│ │ ├── Metas.tsx # Metas e progresso por centro de custo
|
||
│ │ └── Alertas.tsx # Configuração de alertas inteligentes
|
||
│ ├── services/ # Axios clients e API calls
|
||
│ │ └── api.ts
|
||
│ ├── types/ # Interfaces TypeScript
|
||
│ └── index.css # Tailwind directives
|
||
├── vite.config.ts
|
||
├── tailwind.config.js
|
||
├── tsconfig.json
|
||
└── package.json
|
||
</code></pre>
|
||
<h2 id="4-modelo-de-dados">4. Modelo de Dados</h2>
|
||
<h3 id="41-diagrama-de-entidades">4.1 Diagrama de Entidades</h3>
|
||
<p>O sistema possui 21 entidades principais:</p>
|
||
<pre><code>perfis ──< usuarios ──< demandas ──< itens_linha
|
||
│ │
|
||
│ ├──< propostas
|
||
│ │
|
||
│ ├──< workflow_aprovacao
|
||
│ │
|
||
│ └──< ordens_servico ──< avaliacoes
|
||
│
|
||
└──< audit_log
|
||
|
||
locais ──< centros_custo ──< orcamento_planejado
|
||
|
||
categorias ──< demandas
|
||
|
||
fornecedores ──< certidoes
|
||
fornecedores ──< propostas
|
||
|
||
alertas (standalone)
|
||
|
||
locais ──< esg_metricas
|
||
locais ──< esg_metas
|
||
|
||
centros_custo ──< kpis
|
||
centros_custo ──< metas
|
||
|
||
centros_custo ──< alertas_config
|
||
categorias ──< alertas_config
|
||
</code></pre>
|
||
<h3 id="42-descricao-das-entidades">4.2 Descrição das Entidades</h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>#</th>
|
||
<th>Entidade</th>
|
||
<th>Descrição</th>
|
||
<th>Campos Principais</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>1</td>
|
||
<td><strong>perfis</strong></td>
|
||
<td>Perfis de acesso (RBAC)</td>
|
||
<td>id, nome, descricao, permissoes (JSON)</td>
|
||
</tr>
|
||
<tr>
|
||
<td>2</td>
|
||
<td><strong>usuarios</strong></td>
|
||
<td>Usuários do sistema</td>
|
||
<td>id, nome, email, senha_hash, perfil_id, ativo, ultimo_acesso</td>
|
||
</tr>
|
||
<tr>
|
||
<td>3</td>
|
||
<td><strong>locais</strong></td>
|
||
<td>Unidades/edifícios</td>
|
||
<td>id, nome, endereco, cidade, estado, cnpj, ativo</td>
|
||
</tr>
|
||
<tr>
|
||
<td>4</td>
|
||
<td><strong>centros_custo</strong></td>
|
||
<td>Centros de custo por local</td>
|
||
<td>id, codigo, descricao, local_id, ativo</td>
|
||
</tr>
|
||
<tr>
|
||
<td>5</td>
|
||
<td><strong>categorias</strong></td>
|
||
<td>Categorias de serviço</td>
|
||
<td>id, nome, descricao, sla_dias, ativo</td>
|
||
</tr>
|
||
<tr>
|
||
<td>6</td>
|
||
<td><strong>fornecedores</strong></td>
|
||
<td>Cadastro de fornecedores</td>
|
||
<td>id, razao_social, cnpj, contato, email, telefone, ativo, rating</td>
|
||
</tr>
|
||
<tr>
|
||
<td>7</td>
|
||
<td><strong>certidoes</strong></td>
|
||
<td>Certidões de fornecedores</td>
|
||
<td>id, fornecedor_id, tipo, arquivo_url, validade, status</td>
|
||
</tr>
|
||
<tr>
|
||
<td>8</td>
|
||
<td><strong>orcamento_planejado</strong></td>
|
||
<td>Budget por centro de custo/ano</td>
|
||
<td>id, centro_custo_id, ano, mes, valor_planejado, valor_realizado</td>
|
||
</tr>
|
||
<tr>
|
||
<td>9</td>
|
||
<td><strong>demandas</strong></td>
|
||
<td>Demandas de serviço</td>
|
||
<td>id, titulo, descricao, local_id, categoria_id, solicitante_id, status, prioridade, valor_estimado, created_at</td>
|
||
</tr>
|
||
<tr>
|
||
<td>10</td>
|
||
<td><strong>itens_linha</strong></td>
|
||
<td>Itens detalhados da demanda</td>
|
||
<td>id, demanda_id, descricao, quantidade, unidade, valor_unitario</td>
|
||
</tr>
|
||
<tr>
|
||
<td>11</td>
|
||
<td><strong>propostas</strong></td>
|
||
<td>Propostas de fornecedores</td>
|
||
<td>id, demanda_id, fornecedor_id, valor_total, arquivo_url, data_validade, status, observacoes</td>
|
||
</tr>
|
||
<tr>
|
||
<td>12</td>
|
||
<td><strong>workflow_aprovacao</strong></td>
|
||
<td>Etapas de aprovação</td>
|
||
<td>id, demanda_id, etapa, aprovador_id, status, comentario, data_acao</td>
|
||
</tr>
|
||
<tr>
|
||
<td>13</td>
|
||
<td><strong>ordens_servico</strong></td>
|
||
<td>Ordens de serviço emitidas</td>
|
||
<td>id, demanda_id, proposta_id, numero_os, data_inicio, data_fim_prevista, data_fim_real, status</td>
|
||
</tr>
|
||
<tr>
|
||
<td>14</td>
|
||
<td><strong>avaliacoes</strong></td>
|
||
<td>Avaliação pós-execução</td>
|
||
<td>id, ordem_servico_id, avaliador_id, nota, comentario, created_at</td>
|
||
</tr>
|
||
<tr>
|
||
<td>15</td>
|
||
<td><strong>audit_log</strong></td>
|
||
<td>Log de auditoria</td>
|
||
<td>id, usuario_id, acao, entidade, entidade_id, dados_antes, dados_depois, ip, created_at</td>
|
||
</tr>
|
||
<tr>
|
||
<td>16</td>
|
||
<td><strong>alertas</strong></td>
|
||
<td>Notificações e alertas</td>
|
||
<td>id, usuario_id, tipo, mensagem, lido, referencia_tipo, referencia_id, created_at</td>
|
||
</tr>
|
||
<tr>
|
||
<td>17</td>
|
||
<td><strong>esg_metricas</strong></td>
|
||
<td>Métricas ambientais ESG</td>
|
||
<td>id, local_id, tipo (energia/agua/residuos/emissoes_co2), valor, unidade_medida, periodo, observacoes, created_at</td>
|
||
</tr>
|
||
<tr>
|
||
<td>18</td>
|
||
<td><strong>esg_metas</strong></td>
|
||
<td>Metas ESG</td>
|
||
<td>id, local_id, tipo, descricao, valor_alvo, valor_atual, percentual_atingido, status, prazo, created_at</td>
|
||
</tr>
|
||
<tr>
|
||
<td>19</td>
|
||
<td><strong>kpis</strong></td>
|
||
<td>Indicadores de performance calculados</td>
|
||
<td>id, nome, valor, unidade, status_semaforo, centro_custo_id, periodo, calculated_at</td>
|
||
</tr>
|
||
<tr>
|
||
<td>20</td>
|
||
<td><strong>metas</strong></td>
|
||
<td>Metas por centro de custo</td>
|
||
<td>id, centro_custo_id, tipo (orcamento/operacional/esg), descricao, valor_alvo, valor_atual, percentual_atingido, status, prazo, created_at</td>
|
||
</tr>
|
||
<tr>
|
||
<td>21</td>
|
||
<td><strong>alertas_config</strong></td>
|
||
<td>Configuração de alertas inteligentes</td>
|
||
<td>id, tipo, centro_custo_id, categoria_id, limite_percentual, notificar_usuarios (JSON), ativo, created_at</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3 id="43-perfis-de-acesso-rbac">4.3 Perfis de Acesso (RBAC)</h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Perfil</th>
|
||
<th>Permissões</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><strong>Admin</strong></td>
|
||
<td>Acesso total ao sistema, gestão de usuários e configurações</td>
|
||
</tr>
|
||
<tr>
|
||
<td><strong>Gestor Facilities</strong></td>
|
||
<td>CRUD de demandas, fornecedores, propostas, OS; aprovação nível 1</td>
|
||
</tr>
|
||
<tr>
|
||
<td><strong>Aprovador Financeiro</strong></td>
|
||
<td>Aprovação nível 2 (financeiro), visualização de orçamento</td>
|
||
</tr>
|
||
<tr>
|
||
<td><strong>Diretoria</strong></td>
|
||
<td>Aprovação nível 3 (alçada máxima), dashboard executivo</td>
|
||
</tr>
|
||
<tr>
|
||
<td><strong>Solicitante</strong></td>
|
||
<td>Abertura de demandas, acompanhamento do próprio pedido</td>
|
||
</tr>
|
||
<tr>
|
||
<td><strong>Fornecedor</strong></td>
|
||
<td>Envio de propostas, acompanhamento de OS atribuídas</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h2 id="5-api-endpoints">5. API — Endpoints</h2>
|
||
<h3 id="51-autenticacao-apiauth">5.1 Autenticação (<code>/api/auth</code>)</h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Método</th>
|
||
<th>Rota</th>
|
||
<th>Descrição</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>POST</td>
|
||
<td><code>/api/auth/login</code></td>
|
||
<td>Login com email/senha → JWT</td>
|
||
</tr>
|
||
<tr>
|
||
<td>POST</td>
|
||
<td><code>/api/auth/refresh</code></td>
|
||
<td>Renovar token</td>
|
||
</tr>
|
||
<tr>
|
||
<td>POST</td>
|
||
<td><code>/api/auth/logout</code></td>
|
||
<td>Invalidar token</td>
|
||
</tr>
|
||
<tr>
|
||
<td>GET</td>
|
||
<td><code>/api/auth/me</code></td>
|
||
<td>Dados do usuário logado</td>
|
||
</tr>
|
||
<tr>
|
||
<td>POST</td>
|
||
<td><code>/api/auth/forgot-password</code></td>
|
||
<td>Solicitar reset de senha</td>
|
||
</tr>
|
||
<tr>
|
||
<td>POST</td>
|
||
<td><code>/api/auth/reset-password</code></td>
|
||
<td>Resetar senha com token</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3 id="52-usuarios-apiusers">5.2 Usuários (<code>/api/users</code>)</h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Método</th>
|
||
<th>Rota</th>
|
||
<th>Descrição</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>GET</td>
|
||
<td><code>/api/users</code></td>
|
||
<td>Listar usuários (paginado)</td>
|
||
</tr>
|
||
<tr>
|
||
<td>GET</td>
|
||
<td><code>/api/users/:id</code></td>
|
||
<td>Detalhes do usuário</td>
|
||
</tr>
|
||
<tr>
|
||
<td>POST</td>
|
||
<td><code>/api/users</code></td>
|
||
<td>Criar usuário</td>
|
||
</tr>
|
||
<tr>
|
||
<td>PATCH</td>
|
||
<td><code>/api/users/:id</code></td>
|
||
<td>Atualizar usuário</td>
|
||
</tr>
|
||
<tr>
|
||
<td>DELETE</td>
|
||
<td><code>/api/users/:id</code></td>
|
||
<td>Desativar usuário</td>
|
||
</tr>
|
||
<tr>
|
||
<td>GET</td>
|
||
<td><code>/api/perfis</code></td>
|
||
<td>Listar perfis</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3 id="53-locais-apilocais">5.3 Locais (<code>/api/locais</code>)</h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Método</th>
|
||
<th>Rota</th>
|
||
<th>Descrição</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>GET</td>
|
||
<td><code>/api/locais</code></td>
|
||
<td>Listar locais</td>
|
||
</tr>
|
||
<tr>
|
||
<td>GET</td>
|
||
<td><code>/api/locais/:id</code></td>
|
||
<td>Detalhes do local</td>
|
||
</tr>
|
||
<tr>
|
||
<td>POST</td>
|
||
<td><code>/api/locais</code></td>
|
||
<td>Criar local</td>
|
||
</tr>
|
||
<tr>
|
||
<td>PATCH</td>
|
||
<td><code>/api/locais/:id</code></td>
|
||
<td>Atualizar local</td>
|
||
</tr>
|
||
<tr>
|
||
<td>DELETE</td>
|
||
<td><code>/api/locais/:id</code></td>
|
||
<td>Desativar local</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3 id="54-centros-de-custo-apicentros-custo">5.4 Centros de Custo (<code>/api/centros-custo</code>)</h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Método</th>
|
||
<th>Rota</th>
|
||
<th>Descrição</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>GET</td>
|
||
<td><code>/api/centros-custo</code></td>
|
||
<td>Listar centros de custo</td>
|
||
</tr>
|
||
<tr>
|
||
<td>GET</td>
|
||
<td><code>/api/centros-custo/:id</code></td>
|
||
<td>Detalhes</td>
|
||
</tr>
|
||
<tr>
|
||
<td>POST</td>
|
||
<td><code>/api/centros-custo</code></td>
|
||
<td>Criar centro de custo</td>
|
||
</tr>
|
||
<tr>
|
||
<td>PATCH</td>
|
||
<td><code>/api/centros-custo/:id</code></td>
|
||
<td>Atualizar</td>
|
||
</tr>
|
||
<tr>
|
||
<td>DELETE</td>
|
||
<td><code>/api/centros-custo/:id</code></td>
|
||
<td>Desativar</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3 id="55-categorias-apicategorias">5.5 Categorias (<code>/api/categorias</code>)</h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Método</th>
|
||
<th>Rota</th>
|
||
<th>Descrição</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>GET</td>
|
||
<td><code>/api/categorias</code></td>
|
||
<td>Listar categorias</td>
|
||
</tr>
|
||
<tr>
|
||
<td>GET</td>
|
||
<td><code>/api/categorias/:id</code></td>
|
||
<td>Detalhes</td>
|
||
</tr>
|
||
<tr>
|
||
<td>POST</td>
|
||
<td><code>/api/categorias</code></td>
|
||
<td>Criar categoria</td>
|
||
</tr>
|
||
<tr>
|
||
<td>PATCH</td>
|
||
<td><code>/api/categorias/:id</code></td>
|
||
<td>Atualizar</td>
|
||
</tr>
|
||
<tr>
|
||
<td>DELETE</td>
|
||
<td><code>/api/categorias/:id</code></td>
|
||
<td>Desativar</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3 id="56-fornecedores-apifornecedores">5.6 Fornecedores (<code>/api/fornecedores</code>)</h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Método</th>
|
||
<th>Rota</th>
|
||
<th>Descrição</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>GET</td>
|
||
<td><code>/api/fornecedores</code></td>
|
||
<td>Listar fornecedores</td>
|
||
</tr>
|
||
<tr>
|
||
<td>GET</td>
|
||
<td><code>/api/fornecedores/:id</code></td>
|
||
<td>Detalhes com certidões</td>
|
||
</tr>
|
||
<tr>
|
||
<td>POST</td>
|
||
<td><code>/api/fornecedores</code></td>
|
||
<td>Cadastrar fornecedor</td>
|
||
</tr>
|
||
<tr>
|
||
<td>PATCH</td>
|
||
<td><code>/api/fornecedores/:id</code></td>
|
||
<td>Atualizar fornecedor</td>
|
||
</tr>
|
||
<tr>
|
||
<td>DELETE</td>
|
||
<td><code>/api/fornecedores/:id</code></td>
|
||
<td>Desativar</td>
|
||
</tr>
|
||
<tr>
|
||
<td>POST</td>
|
||
<td><code>/api/fornecedores/:id/certidoes</code></td>
|
||
<td>Upload de certidão</td>
|
||
</tr>
|
||
<tr>
|
||
<td>GET</td>
|
||
<td><code>/api/fornecedores/:id/certidoes</code></td>
|
||
<td>Listar certidões</td>
|
||
</tr>
|
||
<tr>
|
||
<td>DELETE</td>
|
||
<td><code>/api/fornecedores/:id/certidoes/:certidaoId</code></td>
|
||
<td>Remover certidão</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3 id="57-demandas-apidemandas">5.7 Demandas (<code>/api/demandas</code>)</h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Método</th>
|
||
<th>Rota</th>
|
||
<th>Descrição</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>GET</td>
|
||
<td><code>/api/demandas</code></td>
|
||
<td>Listar demandas (filtros: status, local, categoria, período)</td>
|
||
</tr>
|
||
<tr>
|
||
<td>GET</td>
|
||
<td><code>/api/demandas/:id</code></td>
|
||
<td>Detalhes completos da demanda</td>
|
||
</tr>
|
||
<tr>
|
||
<td>POST</td>
|
||
<td><code>/api/demandas</code></td>
|
||
<td>Criar nova demanda</td>
|
||
</tr>
|
||
<tr>
|
||
<td>PATCH</td>
|
||
<td><code>/api/demandas/:id</code></td>
|
||
<td>Atualizar demanda</td>
|
||
</tr>
|
||
<tr>
|
||
<td>DELETE</td>
|
||
<td><code>/api/demandas/:id</code></td>
|
||
<td>Cancelar demanda</td>
|
||
</tr>
|
||
<tr>
|
||
<td>POST</td>
|
||
<td><code>/api/demandas/:id/itens</code></td>
|
||
<td>Adicionar item de linha</td>
|
||
</tr>
|
||
<tr>
|
||
<td>PATCH</td>
|
||
<td><code>/api/demandas/:id/itens/:itemId</code></td>
|
||
<td>Atualizar item</td>
|
||
</tr>
|
||
<tr>
|
||
<td>DELETE</td>
|
||
<td><code>/api/demandas/:id/itens/:itemId</code></td>
|
||
<td>Remover item</td>
|
||
</tr>
|
||
<tr>
|
||
<td>POST</td>
|
||
<td><code>/api/demandas/:id/enviar-cotacao</code></td>
|
||
<td>Enviar para cotação</td>
|
||
</tr>
|
||
<tr>
|
||
<td>GET</td>
|
||
<td><code>/api/demandas/:id/comparativo</code></td>
|
||
<td>Comparativo de propostas</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3 id="58-propostas-apipropostas">5.8 Propostas (<code>/api/propostas</code>)</h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Método</th>
|
||
<th>Rota</th>
|
||
<th>Descrição</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>GET</td>
|
||
<td><code>/api/propostas</code></td>
|
||
<td>Listar propostas</td>
|
||
</tr>
|
||
<tr>
|
||
<td>GET</td>
|
||
<td><code>/api/propostas/:id</code></td>
|
||
<td>Detalhes da proposta</td>
|
||
</tr>
|
||
<tr>
|
||
<td>POST</td>
|
||
<td><code>/api/propostas</code></td>
|
||
<td>Submeter proposta (fornecedor)</td>
|
||
</tr>
|
||
<tr>
|
||
<td>PATCH</td>
|
||
<td><code>/api/propostas/:id</code></td>
|
||
<td>Atualizar proposta</td>
|
||
</tr>
|
||
<tr>
|
||
<td>DELETE</td>
|
||
<td><code>/api/propostas/:id</code></td>
|
||
<td>Retirar proposta</td>
|
||
</tr>
|
||
<tr>
|
||
<td>POST</td>
|
||
<td><code>/api/propostas/:id/aceitar</code></td>
|
||
<td>Aceitar proposta</td>
|
||
</tr>
|
||
<tr>
|
||
<td>POST</td>
|
||
<td><code>/api/propostas/:id/rejeitar</code></td>
|
||
<td>Rejeitar proposta</td>
|
||
</tr>
|
||
<tr>
|
||
<td>POST</td>
|
||
<td><code>/api/propostas/:id/ocr</code></td>
|
||
<td>Processar OCR do arquivo</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3 id="59-orcamento-apiorcamento">5.9 Orçamento (<code>/api/orcamento</code>)</h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Método</th>
|
||
<th>Rota</th>
|
||
<th>Descrição</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>GET</td>
|
||
<td><code>/api/orcamento</code></td>
|
||
<td>Orçamento geral (filtros: ano, local, centro_custo)</td>
|
||
</tr>
|
||
<tr>
|
||
<td>GET</td>
|
||
<td><code>/api/orcamento/:id</code></td>
|
||
<td>Detalhes da linha orçamentária</td>
|
||
</tr>
|
||
<tr>
|
||
<td>POST</td>
|
||
<td><code>/api/orcamento</code></td>
|
||
<td>Criar linha orçamentária</td>
|
||
</tr>
|
||
<tr>
|
||
<td>PATCH</td>
|
||
<td><code>/api/orcamento/:id</code></td>
|
||
<td>Atualizar valores</td>
|
||
</tr>
|
||
<tr>
|
||
<td>GET</td>
|
||
<td><code>/api/orcamento/resumo</code></td>
|
||
<td>Resumo planejado vs realizado</td>
|
||
</tr>
|
||
<tr>
|
||
<td>GET</td>
|
||
<td><code>/api/orcamento/projecao</code></td>
|
||
<td>Projeção de gastos</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3 id="510-workflow-apiworkflow">5.10 Workflow (<code>/api/workflow</code>)</h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Método</th>
|
||
<th>Rota</th>
|
||
<th>Descrição</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>GET</td>
|
||
<td><code>/api/workflow/pendentes</code></td>
|
||
<td>Aprovações pendentes do usuário logado</td>
|
||
</tr>
|
||
<tr>
|
||
<td>GET</td>
|
||
<td><code>/api/workflow/demanda/:demandaId</code></td>
|
||
<td>Histórico de aprovações da demanda</td>
|
||
</tr>
|
||
<tr>
|
||
<td>POST</td>
|
||
<td><code>/api/workflow/aprovar</code></td>
|
||
<td>Aprovar etapa</td>
|
||
</tr>
|
||
<tr>
|
||
<td>POST</td>
|
||
<td><code>/api/workflow/rejeitar</code></td>
|
||
<td>Rejeitar etapa</td>
|
||
</tr>
|
||
<tr>
|
||
<td>POST</td>
|
||
<td><code>/api/workflow/devolver</code></td>
|
||
<td>Devolver para correção</td>
|
||
</tr>
|
||
<tr>
|
||
<td>GET</td>
|
||
<td><code>/api/workflow/alçadas</code></td>
|
||
<td>Consultar alçadas configuradas</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3 id="511-dashboard-apidashboard">5.11 Dashboard (<code>/api/dashboard</code>)</h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Método</th>
|
||
<th>Rota</th>
|
||
<th>Descrição</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>GET</td>
|
||
<td><code>/api/dashboard/indicadores</code></td>
|
||
<td>KPIs gerais</td>
|
||
</tr>
|
||
<tr>
|
||
<td>GET</td>
|
||
<td><code>/api/dashboard/demandas-por-status</code></td>
|
||
<td>Demandas agrupadas por status</td>
|
||
</tr>
|
||
<tr>
|
||
<td>GET</td>
|
||
<td><code>/api/dashboard/gastos-por-local</code></td>
|
||
<td>Gastos por unidade</td>
|
||
</tr>
|
||
<tr>
|
||
<td>GET</td>
|
||
<td><code>/api/dashboard/gastos-por-categoria</code></td>
|
||
<td>Gastos por categoria</td>
|
||
</tr>
|
||
<tr>
|
||
<td>GET</td>
|
||
<td><code>/api/dashboard/evolucao-mensal</code></td>
|
||
<td>Série temporal de gastos</td>
|
||
</tr>
|
||
<tr>
|
||
<td>GET</td>
|
||
<td><code>/api/dashboard/top-fornecedores</code></td>
|
||
<td>Ranking de fornecedores</td>
|
||
</tr>
|
||
<tr>
|
||
<td>GET</td>
|
||
<td><code>/api/dashboard/sla</code></td>
|
||
<td>Indicadores de SLA</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3 id="512-ordens-de-servico-apiordens-servico">5.12 Ordens de Serviço (<code>/api/ordens-servico</code>)</h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Método</th>
|
||
<th>Rota</th>
|
||
<th>Descrição</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>GET</td>
|
||
<td><code>/api/ordens-servico</code></td>
|
||
<td>Listar OS</td>
|
||
</tr>
|
||
<tr>
|
||
<td>GET</td>
|
||
<td><code>/api/ordens-servico/:id</code></td>
|
||
<td>Detalhes da OS</td>
|
||
</tr>
|
||
<tr>
|
||
<td>POST</td>
|
||
<td><code>/api/ordens-servico</code></td>
|
||
<td>Emitir OS</td>
|
||
</tr>
|
||
<tr>
|
||
<td>PATCH</td>
|
||
<td><code>/api/ordens-servico/:id</code></td>
|
||
<td>Atualizar OS</td>
|
||
</tr>
|
||
<tr>
|
||
<td>POST</td>
|
||
<td><code>/api/ordens-servico/:id/iniciar</code></td>
|
||
<td>Marcar início da execução</td>
|
||
</tr>
|
||
<tr>
|
||
<td>POST</td>
|
||
<td><code>/api/ordens-servico/:id/concluir</code></td>
|
||
<td>Marcar conclusão</td>
|
||
</tr>
|
||
<tr>
|
||
<td>POST</td>
|
||
<td><code>/api/ordens-servico/:id/avaliar</code></td>
|
||
<td>Avaliar serviço prestado</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3 id="513-alertas-apialertas">5.13 Alertas (<code>/api/alertas</code>)</h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Método</th>
|
||
<th>Rota</th>
|
||
<th>Descrição</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>GET</td>
|
||
<td><code>/api/alertas</code></td>
|
||
<td>Listar alertas do usuário</td>
|
||
</tr>
|
||
<tr>
|
||
<td>PATCH</td>
|
||
<td><code>/api/alertas/:id/lido</code></td>
|
||
<td>Marcar como lido</td>
|
||
</tr>
|
||
<tr>
|
||
<td>DELETE</td>
|
||
<td><code>/api/alertas/:id</code></td>
|
||
<td>Remover alerta</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3 id="514-esg-sustentabilidade-apiesg">5.14 ESG / Sustentabilidade (<code>/api/esg</code>)</h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Método</th>
|
||
<th>Rota</th>
|
||
<th>Descrição</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>GET</td>
|
||
<td><code>/api/esg/metricas</code></td>
|
||
<td>Listar métricas ambientais (filtros: unidade, período, tipo)</td>
|
||
</tr>
|
||
<tr>
|
||
<td>POST</td>
|
||
<td><code>/api/esg/metricas</code></td>
|
||
<td>Registrar métrica ambiental</td>
|
||
</tr>
|
||
<tr>
|
||
<td>PATCH</td>
|
||
<td><code>/api/esg/metricas/:id</code></td>
|
||
<td>Atualizar métrica</td>
|
||
</tr>
|
||
<tr>
|
||
<td>DELETE</td>
|
||
<td><code>/api/esg/metricas/:id</code></td>
|
||
<td>Remover métrica</td>
|
||
</tr>
|
||
<tr>
|
||
<td>GET</td>
|
||
<td><code>/api/esg/dashboard</code></td>
|
||
<td>Dashboard consolidado ESG por unidade/período</td>
|
||
</tr>
|
||
<tr>
|
||
<td>GET</td>
|
||
<td><code>/api/esg/metas</code></td>
|
||
<td>Listar metas ESG</td>
|
||
</tr>
|
||
<tr>
|
||
<td>POST</td>
|
||
<td><code>/api/esg/metas</code></td>
|
||
<td>Criar meta ESG</td>
|
||
</tr>
|
||
<tr>
|
||
<td>PATCH</td>
|
||
<td><code>/api/esg/metas/:id</code></td>
|
||
<td>Atualizar meta ESG</td>
|
||
</tr>
|
||
<tr>
|
||
<td>GET</td>
|
||
<td><code>/api/esg/metas/:id/progresso</code></td>
|
||
<td>Progresso da meta ESG</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<p><strong>Exemplo — POST <code>/api/esg/metricas</code>:</strong></p>
|
||
<pre><code class="language-json">// Request
|
||
{
|
||
"local_id": 3,
|
||
"tipo": "energia",
|
||
"valor": 12500.50,
|
||
"unidade_medida": "kWh",
|
||
"periodo": "2025-06",
|
||
"observacoes": "Consumo sede administrativa"
|
||
}
|
||
// Response 201
|
||
{
|
||
"id": 42,
|
||
"local_id": 3,
|
||
"tipo": "energia",
|
||
"valor": 12500.50,
|
||
"unidade_medida": "kWh",
|
||
"periodo": "2025-06",
|
||
"created_at": "2025-06-30T14:00:00Z"
|
||
}
|
||
</code></pre>
|
||
<p><strong>Tipos de métricas suportados:</strong> <code>energia</code> (kWh), <code>agua</code> (m³), <code>residuos</code> (kg), <code>emissoes_co2</code> (tCO₂e).</p>
|
||
<h3 id="515-kpis-indicadores-de-performance-apikpis">5.15 KPIs — Indicadores de Performance (<code>/api/kpis</code>)</h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Método</th>
|
||
<th>Rota</th>
|
||
<th>Descrição</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>GET</td>
|
||
<td><code>/api/kpis</code></td>
|
||
<td>Listar KPIs calculados (filtros: categoria, ano, centro_custo)</td>
|
||
</tr>
|
||
<tr>
|
||
<td>GET</td>
|
||
<td><code>/api/kpis/dashboard</code></td>
|
||
<td>Dashboard de KPIs com status semáforo</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<p><strong>KPIs calculados automaticamente:</strong></p>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>KPI</th>
|
||
<th>Fórmula</th>
|
||
<th>Verde</th>
|
||
<th>Amarelo</th>
|
||
<th>Vermelho</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>% Orçamento Consumido</td>
|
||
<td>realizado / planejado × 100</td>
|
||
<td>≤ 80%</td>
|
||
<td>81–100%</td>
|
||
<td>> 100%</td>
|
||
</tr>
|
||
<tr>
|
||
<td>Tempo Médio de OS</td>
|
||
<td>média(data_fim_real - data_inicio)</td>
|
||
<td>≤ SLA</td>
|
||
<td>SLA+20%</td>
|
||
<td>> SLA+20%</td>
|
||
</tr>
|
||
<tr>
|
||
<td>Rating Fornecedores</td>
|
||
<td>média das avaliações</td>
|
||
<td>≥ 4.0</td>
|
||
<td>3.0–3.9</td>
|
||
<td>< 3.0</td>
|
||
</tr>
|
||
<tr>
|
||
<td>Taxa Conclusão Demandas</td>
|
||
<td>concluídas / total × 100</td>
|
||
<td>≥ 90%</td>
|
||
<td>70–89%</td>
|
||
<td>< 70%</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<p><strong>Exemplo — GET <code>/api/kpis/dashboard</code>:</strong></p>
|
||
<pre><code class="language-json">// Response 200
|
||
{
|
||
"periodo": "2025-06",
|
||
"kpis": [
|
||
{
|
||
"nome": "orcamento_consumido",
|
||
"valor": 78.5,
|
||
"unidade": "%",
|
||
"status": "verde",
|
||
"centro_custo": "ADM-001"
|
||
},
|
||
{
|
||
"nome": "tempo_medio_os",
|
||
"valor": 12.3,
|
||
"unidade": "dias",
|
||
"status": "amarelo",
|
||
"centro_custo": "ADM-001"
|
||
}
|
||
]
|
||
}
|
||
</code></pre>
|
||
<h3 id="516-auditoria-e-compliance-apiaudit">5.16 Auditoria e Compliance (<code>/api/audit</code>)</h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Método</th>
|
||
<th>Rota</th>
|
||
<th>Descrição</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>GET</td>
|
||
<td><code>/api/audit/logs</code></td>
|
||
<td>Trilha de auditoria completa (filtros: usuario, entidade, período, ação)</td>
|
||
</tr>
|
||
<tr>
|
||
<td>GET</td>
|
||
<td><code>/api/audit/compliance-report</code></td>
|
||
<td>Relatório de conformidade por período</td>
|
||
</tr>
|
||
<tr>
|
||
<td>GET</td>
|
||
<td><code>/api/audit/export</code></td>
|
||
<td>Exportação de logs em CSV ou JSON (<code>?format=csv\|json</code>)</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<p><strong>Exemplo — GET <code>/api/audit/logs?entidade=demandas&periodo_inicio=2025-06-01</code>:</strong></p>
|
||
<pre><code class="language-json">// Response 200
|
||
{
|
||
"total": 245,
|
||
"page": 1,
|
||
"data": [
|
||
{
|
||
"id": 1023,
|
||
"usuario": "joao.silva@empresa.com",
|
||
"acao": "UPDATE",
|
||
"entidade": "demandas",
|
||
"entidade_id": 87,
|
||
"dados_antes": { "status": "EM_COTACAO" },
|
||
"dados_depois": { "status": "PROPOSTAS_RECEBIDAS" },
|
||
"ip": "192.168.1.50",
|
||
"created_at": "2025-06-15T10:32:00Z"
|
||
}
|
||
]
|
||
}
|
||
</code></pre>
|
||
<h3 id="517-importacao-de-dados-apiimport">5.17 Importação de Dados (<code>/api/import</code>)</h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Método</th>
|
||
<th>Rota</th>
|
||
<th>Descrição</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>POST</td>
|
||
<td><code>/api/import/excel</code></td>
|
||
<td>Upload de planilha Excel/CSV com validação automática</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<p><strong>Tipos de importação:</strong> <code>orcamento</code>, <code>demandas</code>.</p>
|
||
<p><strong>Exemplo — POST <code>/api/import/excel</code> (multipart/form-data):</strong></p>
|
||
<pre><code class="language-json">// Request: file=planilha.xlsx, tipo=orcamento
|
||
// Response 200
|
||
{
|
||
"status": "success",
|
||
"registros_importados": 48,
|
||
"registros_com_erro": 2,
|
||
"erros": [
|
||
{ "linha": 15, "campo": "valor_planejado", "mensagem": "Valor inválido" },
|
||
{ "linha": 32, "campo": "centro_custo_id", "mensagem": "Centro de custo não encontrado" }
|
||
]
|
||
}
|
||
</code></pre>
|
||
<h3 id="518-relatorios-automatizados-apirelatorios">5.18 Relatórios Automatizados (<code>/api/relatorios</code>)</h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Método</th>
|
||
<th>Rota</th>
|
||
<th>Descrição</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>GET</td>
|
||
<td><code>/api/relatorios/orcamento-mensal</code></td>
|
||
<td>Relatório de orçamento mensal (filtros: ano, mês, local)</td>
|
||
</tr>
|
||
<tr>
|
||
<td>GET</td>
|
||
<td><code>/api/relatorios/demandas-periodo</code></td>
|
||
<td>Demandas por período com status e valores</td>
|
||
</tr>
|
||
<tr>
|
||
<td>GET</td>
|
||
<td><code>/api/relatorios/fornecedores-ranking</code></td>
|
||
<td>Ranking de fornecedores com nota, valor e volume</td>
|
||
</tr>
|
||
<tr>
|
||
<td>GET</td>
|
||
<td><code>/api/relatorios/os-performance</code></td>
|
||
<td>Performance de OS (SLA, tempo médio, conclusão)</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<p><strong>Todos os relatórios suportam <code>?format=json|csv|pdf</code>.</strong></p>
|
||
<p><strong>Exemplo — GET <code>/api/relatorios/fornecedores-ranking?ano=2025&limit=10</code>:</strong></p>
|
||
<pre><code class="language-json">// Response 200
|
||
{
|
||
"periodo": "2025",
|
||
"ranking": [
|
||
{
|
||
"posicao": 1,
|
||
"fornecedor": "TechServ Ltda",
|
||
"rating": 4.8,
|
||
"total_os": 23,
|
||
"valor_total": 187500.00,
|
||
"sla_cumprido": 95.6
|
||
}
|
||
]
|
||
}
|
||
</code></pre>
|
||
<h3 id="519-metas-e-progresso-apimetas">5.19 Metas e Progresso (<code>/api/metas</code>)</h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Método</th>
|
||
<th>Rota</th>
|
||
<th>Descrição</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>GET</td>
|
||
<td><code>/api/metas</code></td>
|
||
<td>Listar metas (filtros: centro_custo, tipo, status)</td>
|
||
</tr>
|
||
<tr>
|
||
<td>POST</td>
|
||
<td><code>/api/metas</code></td>
|
||
<td>Criar meta</td>
|
||
</tr>
|
||
<tr>
|
||
<td>PATCH</td>
|
||
<td><code>/api/metas/:id</code></td>
|
||
<td>Atualizar meta</td>
|
||
</tr>
|
||
<tr>
|
||
<td>DELETE</td>
|
||
<td><code>/api/metas/:id</code></td>
|
||
<td>Remover meta</td>
|
||
</tr>
|
||
<tr>
|
||
<td>GET</td>
|
||
<td><code>/api/metas/progresso</code></td>
|
||
<td>Progresso geral de todas as metas</td>
|
||
</tr>
|
||
<tr>
|
||
<td>GET</td>
|
||
<td><code>/api/metas/:id/progresso</code></td>
|
||
<td>Progresso de meta específica</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<p><strong>Tipos de meta:</strong> <code>orcamento</code>, <code>operacional</code>, <code>esg</code>.</p>
|
||
<p><strong>Status:</strong> <code>em_andamento</code>, <code>atingida</code>, <code>atrasada</code>.</p>
|
||
<p><strong>Exemplo — POST <code>/api/metas</code>:</strong></p>
|
||
<pre><code class="language-json">// Request
|
||
{
|
||
"centro_custo_id": 5,
|
||
"tipo": "orcamento",
|
||
"descricao": "Reduzir gastos com manutenção em 10%",
|
||
"valor_alvo": 90,
|
||
"unidade": "%",
|
||
"prazo": "2025-12-31"
|
||
}
|
||
// Response 201
|
||
{
|
||
"id": 12,
|
||
"centro_custo_id": 5,
|
||
"tipo": "orcamento",
|
||
"descricao": "Reduzir gastos com manutenção em 10%",
|
||
"valor_alvo": 90,
|
||
"valor_atual": 0,
|
||
"percentual_atingido": 0,
|
||
"status": "em_andamento",
|
||
"prazo": "2025-12-31",
|
||
"created_at": "2025-02-09T15:00:00Z"
|
||
}
|
||
</code></pre>
|
||
<h3 id="520-alertas-inteligentes-apialertas">5.20 Alertas Inteligentes (<code>/api/alertas</code>)</h3>
|
||
<blockquote>
|
||
<p><strong>Nota:</strong> Os endpoints abaixo complementam os alertas básicos da seção 5.13 com configuração avançada e verificação automática.</p>
|
||
</blockquote>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Método</th>
|
||
<th>Rota</th>
|
||
<th>Descrição</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>POST</td>
|
||
<td><code>/api/alertas/configurar</code></td>
|
||
<td>Configurar regra de alerta inteligente</td>
|
||
</tr>
|
||
<tr>
|
||
<td>GET</td>
|
||
<td><code>/api/alertas/configurar</code></td>
|
||
<td>Listar configurações de alertas</td>
|
||
</tr>
|
||
<tr>
|
||
<td>PATCH</td>
|
||
<td><code>/api/alertas/configurar/:id</code></td>
|
||
<td>Atualizar configuração</td>
|
||
</tr>
|
||
<tr>
|
||
<td>DELETE</td>
|
||
<td><code>/api/alertas/configurar/:id</code></td>
|
||
<td>Remover configuração</td>
|
||
</tr>
|
||
<tr>
|
||
<td>POST</td>
|
||
<td><code>/api/alertas/verificar</code></td>
|
||
<td>Disparar verificação manual de todos os alertas</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<p><strong>Tipos de alerta:</strong> <code>orcamento_excedido</code>, <code>certidao_vencendo</code>, <code>os_atrasada</code>, <code>meta_em_risco</code>.</p>
|
||
<p><strong>Exemplo — POST <code>/api/alertas/configurar</code>:</strong></p>
|
||
<pre><code class="language-json">// Request
|
||
{
|
||
"tipo": "orcamento_excedido",
|
||
"centro_custo_id": 5,
|
||
"limite_percentual": 85,
|
||
"notificar_usuarios": [1, 3, 7],
|
||
"ativo": true
|
||
}
|
||
// Response 201
|
||
{
|
||
"id": 8,
|
||
"tipo": "orcamento_excedido",
|
||
"centro_custo_id": 5,
|
||
"limite_percentual": 85,
|
||
"notificar_usuarios": [1, 3, 7],
|
||
"ativo": true,
|
||
"created_at": "2025-02-09T15:00:00Z"
|
||
}
|
||
</code></pre>
|
||
<p><strong>Total: 95 endpoints</strong></p>
|
||
<h2 id="6-autenticacao-e-autorizacao">6. Autenticação e Autorização</h2>
|
||
<h3 id="61-fluxo-jwt">6.1 Fluxo JWT</h3>
|
||
<ol>
|
||
<li>Usuário faz POST <code>/api/auth/login</code> com email e senha</li>
|
||
<li>Backend valida credenciais e retorna <code>{ accessToken, refreshToken }</code></li>
|
||
<li>Frontend armazena tokens e envia <code>Authorization: Bearer <accessToken></code> em todas as requests</li>
|
||
<li>Token expira em 1h; refresh token expira em 7d</li>
|
||
<li>Frontend usa <code>/api/auth/refresh</code> para renovar automaticamente</li>
|
||
</ol>
|
||
<h3 id="62-guards-nestjs">6.2 Guards NestJS</h3>
|
||
<pre><code class="language-typescript">@UseGuards(JwtAuthGuard, RolesGuard)
|
||
@Roles('admin', 'gestor_facilities')
|
||
@Get('demandas')
|
||
findAll() { ... }
|
||
</code></pre>
|
||
<ul>
|
||
<li><strong>JwtAuthGuard</strong>: valida o token JWT</li>
|
||
<li><strong>RolesGuard</strong>: verifica se o perfil do usuário está na lista de roles permitidas</li>
|
||
<li><strong>@CurrentUser()</strong>: decorator customizado que injeta o usuário logado</li>
|
||
</ul>
|
||
<h2 id="7-workflow-de-aprovacao">7. Workflow de Aprovação</h2>
|
||
<h3 id="71-maquina-de-estados">7.1 Máquina de Estados</h3>
|
||
<pre><code>RASCUNHO → EM_ESCOPO → EM_COTAÇÃO → PROPOSTAS_RECEBIDAS
|
||
→ EM_COMPARAÇÃO → AGUARDANDO_APROVAÇÃO → APROVADA
|
||
→ OS_EMITIDA → EM_EXECUÇÃO → CONCLUÍDA → AVALIADA
|
||
|
||
Estados alternativos:
|
||
AGUARDANDO_APROVAÇÃO → REJEITADA
|
||
AGUARDANDO_APROVAÇÃO → DEVOLVIDA → EM_ESCOPO
|
||
Qualquer estado → CANCELADA
|
||
</code></pre>
|
||
<h3 id="72-alcadas-de-aprovacao">7.2 Alçadas de Aprovação</h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Faixa de Valor</th>
|
||
<th>Aprovador</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>Até R$ 5.000</td>
|
||
<td>Gestor Facilities</td>
|
||
</tr>
|
||
<tr>
|
||
<td>R$ 5.001 — R$ 50.000</td>
|
||
<td>Gestor Facilities + Aprovador Financeiro</td>
|
||
</tr>
|
||
<tr>
|
||
<td>R$ 50.001 — R$ 200.000</td>
|
||
<td>Gestor + Financeiro + Diretoria</td>
|
||
</tr>
|
||
<tr>
|
||
<td>Acima de R$ 200.000</td>
|
||
<td>Gestor + Financeiro + Diretoria + CEO</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<p>Cada etapa gera um registro em <code>workflow_aprovacao</code> com timestamp, aprovador e comentário.</p>
|
||
<h2 id="8-como-rodar-localmente">8. Como Rodar Localmente</h2>
|
||
<h3 id="81-pre-requisitos">8.1 Pré-requisitos</h3>
|
||
<ul>
|
||
<li>Node.js 22.x</li>
|
||
<li>npm 10.x</li>
|
||
<li>Git</li>
|
||
</ul>
|
||
<h3 id="82-backend">8.2 Backend</h3>
|
||
<pre><code class="language-bash">cd backend
|
||
cp .env.example .env # Ajustar variáveis
|
||
npm install
|
||
npm run build
|
||
npm run migration:run # Criar tabelas
|
||
npm run seed # Dados iniciais
|
||
npm start # Porta 3000
|
||
</code></pre>
|
||
<h3 id="83-frontend">8.3 Frontend</h3>
|
||
<pre><code class="language-bash">cd frontend
|
||
cp .env.example .env # VITE_API_URL=http://localhost:3000/api
|
||
npm install
|
||
npm run dev # Porta 5173
|
||
</code></pre>
|
||
<h3 id="84-acesso-inicial">8.4 Acesso Inicial</h3>
|
||
<ul>
|
||
<li><strong>Admin:</strong> admin@hefesto.com.br / admin123</li>
|
||
<li><strong>Swagger:</strong> http://localhost:3000/api/docs</li>
|
||
</ul>
|
||
<h2 id="9-deploy-em-producao">9. Deploy em Produção</h2>
|
||
<h3 id="91-infraestrutura">9.1 Infraestrutura</h3>
|
||
<ul>
|
||
<li><strong>Servidor:</strong> DigitalOcean Droplet (Ubuntu 24.04, 2 vCPU, 4GB RAM)</li>
|
||
<li><strong>Proxy reverso:</strong> Nginx</li>
|
||
<li><strong>SSL:</strong> Let's Encrypt (Certbot)</li>
|
||
<li><strong>Processo:</strong> PM2 (backend) / Nginx serve build estático (frontend)</li>
|
||
<li><strong>BD:</strong> PostgreSQL 16</li>
|
||
</ul>
|
||
<h3 id="92-nginx-config">9.2 Nginx Config</h3>
|
||
<pre><code class="language-nginx">server {
|
||
listen 443 ssl;
|
||
server_name hefesto.exemplo.com.br;
|
||
|
||
ssl_certificate /etc/letsencrypt/live/hefesto.exemplo.com.br/fullchain.pem;
|
||
ssl_certificate_key /etc/letsencrypt/live/hefesto.exemplo.com.br/privkey.pem;
|
||
|
||
# Frontend (build estático)
|
||
location / {
|
||
root /var/www/hefesto/frontend/dist;
|
||
try_files $uri $uri/ /index.html;
|
||
}
|
||
|
||
# API Backend
|
||
location /api {
|
||
proxy_pass http://127.0.0.1:3000;
|
||
proxy_set_header Host $host;
|
||
proxy_set_header X-Real-IP $remote_addr;
|
||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||
proxy_set_header X-Forwarded-Proto $scheme;
|
||
}
|
||
}
|
||
</code></pre>
|
||
<h3 id="93-pm2">9.3 PM2</h3>
|
||
<pre><code class="language-bash">cd /var/www/hefesto/backend
|
||
pm2 start dist/main.js --name hefesto-api
|
||
pm2 save
|
||
pm2 startup
|
||
</code></pre>
|
||
<h2 id="10-variaveis-de-ambiente">10. Variáveis de Ambiente</h2>
|
||
<h3 id="backend-env">Backend (<code>.env</code>)</h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Variável</th>
|
||
<th>Descrição</th>
|
||
<th>Exemplo</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>NODE_ENV</code></td>
|
||
<td>Ambiente</td>
|
||
<td><code>production</code></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>PORT</code></td>
|
||
<td>Porta da API</td>
|
||
<td><code>3000</code></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>DB_TYPE</code></td>
|
||
<td>Tipo de banco</td>
|
||
<td><code>postgres</code></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>DB_HOST</code></td>
|
||
<td>Host do banco</td>
|
||
<td><code>localhost</code></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>DB_PORT</code></td>
|
||
<td>Porta do banco</td>
|
||
<td><code>5432</code></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>DB_USERNAME</code></td>
|
||
<td>Usuário do banco</td>
|
||
<td><code>hefesto</code></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>DB_PASSWORD</code></td>
|
||
<td>Senha do banco</td>
|
||
<td><code>***</code></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>DB_DATABASE</code></td>
|
||
<td>Nome do banco</td>
|
||
<td><code>hefesto_prod</code></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>JWT_SECRET</code></td>
|
||
<td>Chave secreta JWT</td>
|
||
<td><code>minha-chave-secreta-256bits</code></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>JWT_EXPIRATION</code></td>
|
||
<td>Tempo de expiração do access token</td>
|
||
<td><code>3600s</code></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>JWT_REFRESH_EXPIRATION</code></td>
|
||
<td>Tempo de expiração do refresh token</td>
|
||
<td><code>7d</code></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>CORS_ORIGIN</code></td>
|
||
<td>Origem permitida</td>
|
||
<td><code>https://hefesto.exemplo.com.br</code></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>OCR_API_KEY</code></td>
|
||
<td>Chave da API de OCR</td>
|
||
<td><code>***</code></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>SMTP_HOST</code></td>
|
||
<td>Servidor SMTP</td>
|
||
<td><code>smtp.gmail.com</code></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>SMTP_PORT</code></td>
|
||
<td>Porta SMTP</td>
|
||
<td><code>587</code></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>SMTP_USER</code></td>
|
||
<td>Usuário SMTP</td>
|
||
<td><code>noreply@hefesto.com.br</code></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>SMTP_PASS</code></td>
|
||
<td>Senha SMTP</td>
|
||
<td><code>***</code></td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3 id="frontend-env">Frontend (<code>.env</code>)</h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Variável</th>
|
||
<th>Descrição</th>
|
||
<th>Exemplo</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>VITE_API_URL</code></td>
|
||
<td>URL base da API</td>
|
||
<td><code>https://hefesto.exemplo.com.br/api</code></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>VITE_APP_NAME</code></td>
|
||
<td>Nome da aplicação</td>
|
||
<td><code>HEFESTO</code></td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<hr />
|
||
<p><em>Documento gerado automaticamente — HEFESTO v2.0</em></p>
|
||
</div>
|
||
|
||
<div class="doc-footer">
|
||
HEFESTO v2.0 · Kislanski Industries | AI Vertice · Fevereiro 2026<br>
|
||
Documento confidencial — Todos os direitos reservados
|
||
</div>
|
||
</body>
|
||
</html> |