Documentação Técnica Completa - Frontend & Backend
Tecnologias:
Tecnologias:
| Entidade | Descrição | Campos Principais |
|---|---|---|
| User | Usuários do sistema | email, password, name, role (ADMIN/USER) |
| Credenciamento | Registro principal | numeroCredenciamento, status, modalidade, 31 campos |
| CredenciamentoLog | Auditoria de alterações | campo, valorAnterior, valorNovo, usuário |
| Anexo | Arquivos anexados | nomeArquivo, caminhoArquivo, tamanho (max 10MB) |
| Orgao | Órgãos públicos | titulo, active |
| Portal | Portais de licitação | titulo, url, active |
| Tipo | Tipos de credenciamento | titulo, active |
| Fornecedor | Fornecedores vencedores | nome, cnpj, active |
ENVIAR_REDE // Enviar para rede
HABILITADOS // Já habilitados
ENVIAR_MKT // Enviar para marketing
AGUARDANDO_HAB // Aguardando habilitação
AGUARDANDO_ESCOLHA // Aguardando escolha
RECURSO // Em recurso
INABILITADA // Inabilitado
NAO_VAMOS // Não vamos participar
ESCOLHIDOS // Fomos escolhidos
REVOGADO // Licitação revogada
DESERTO // Sem participantes
FRACASSADO // Processo fracassado
SUSPENSO // Processo suspenso
CANCELADO // Processo cancelado
IMPUGNADO // Processo impugnado
HOMOLOGADO // Processo homologado
ADJUDICADO // Processo adjudicado
| Rota | Componente | Descrição |
|---|---|---|
/login |
Login.tsx | Autenticação com JWT |
/dashboard |
Dashboard.tsx | Cards estatísticos, gráficos e notificações |
/acompanhamento |
Acompanhamento.tsx | Notificações de prazos (3/5/10 dias) |
/credenciamentos |
CredenciamentoList.tsx | Lista com filtros avançados e export Excel |
/credenciamentos/novo |
CredenciamentoForm.tsx | Formulário com 4 abas |
/usuarios |
UserList.tsx | Gestão de usuários (ADMIN) |
/orgaos |
OrgaoList.tsx | CRUD de órgãos |
/portais |
PortalList.tsx | CRUD de portais |
/tipos |
TipoList.tsx | CRUD de tipos |
/fornecedores |
FornecedorList.tsx | CRUD de fornecedores |
Alertas: Vermelho (<3 dias), Amarelo (<5 dias)
Tabela com auditoria completa:
// 1. Login
const { login } = useAuth();
await login(email, password);
// 2. Token armazenado no localStorage
localStorage.setItem('token', token);
// 3. Interceptor Axios adiciona token automaticamente
api.interceptors.request.use((config) => {
const token = localStorage.getItem('token');
config.headers.Authorization = `Bearer ${token}`;
return config;
});
// 4. PrivateRoute protege rotas
}>
} />
import * as XLSX from 'xlsx';
const exportToExcel = async () => {
const data = await credenciamentoService.export(filters);
const ws = XLSX.utils.json_to_sheet(data);
const wb = XLSX.utils.book_new();
XLSX.utils.book_append_sheet(wb, ws, 'Credenciamentos');
XLSX.writeFile(wb, `credenciamentos_${new Date().toISOString()}.xlsx`);
};
| Módulo | Responsabilidade |
|---|---|
| AuthModule | Autenticação JWT, registro, login |
| CredenciamentoModule | CRUD principal, filtros, notificações, logs |
| UserModule | Gestão de usuários (ADMIN) |
| AnexoModule | Upload/download de arquivos (max 10MB) |
| EmailModule | Envio de notificações via Nodemailer |
| CronModule | Jobs agendados (notificações diárias 8h) |
| OrgaoModule | CRUD de órgãos |
| PortalModule | CRUD de portais |
| TipoModule | CRUD de tipos |
| FornecedorModule | CRUD de fornecedores |
POST /auth/register # Criar novo usuário
POST /auth/login # Autenticar e receber JWT
GET /auth/profile # Buscar perfil autenticado
email + passwordAuthorization: Bearer <token>Toda alteração em credenciamentos gera log automático com:
dataMaximaEnviar: Notificação para ADMINEMAIL_HOST=smtp.gmail.com
EMAIL_PORT=587
EMAIL_USER=seu-email@gmail.com
EMAIL_PASS=sua-senha-app
EMAIL_FROM="Sistema Credenciamento <noreply@credenciamento.com>"
model User {
id Int @id @default(autoincrement())
email String @unique
password String // hash bcrypt
name String
role Role @default(USER)
active Boolean @default(true)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
model Credenciamento {
id Int @id @default(autoincrement())
numeroCredenciamento String?
status StatusCredenciamento
modalidade Modalidade
orgaoId Int
portalId Int?
tipoId Int?
fornecedorId Int?
analistaId Int
// ... 31 campos totais
}
model CredenciamentoLog {
id Int @id @default(autoincrement())
credenciamentoId Int
campo String
valorAnterior String?
valorNovo String?
usuarioNome String
timestamp DateTime @default(now())
}
| Método | Endpoint | Descrição |
|---|---|---|
| POST | /auth/register |
Criar novo usuário |
| POST | /auth/login |
Autenticar e receber JWT |
| GET | /auth/profile |
Buscar perfil autenticado |
| Método | Endpoint | Descrição | Auth |
|---|---|---|---|
| GET | /credenciamentos |
Listar com filtros e paginação | JWT |
| GET | /credenciamentos/notifications |
Notificações de prazos | JWT |
| GET | /credenciamentos/:id |
Buscar por ID (com logs) | JWT |
| POST | /credenciamentos |
Criar novo | JWT |
| PATCH | /credenciamentos/:id |
Atualizar (gera log automático) | JWT |
| DELETE | /credenciamentos/:id |
Deletar | JWT + ADMIN |
GET /credenciamentos?status=HABILITADOS&analistaId=2&page=1&limit=10
Authorization: Bearer <token>
| Parâmetro | Tipo | Descrição |
|---|---|---|
status |
string | Filtrar por status |
analistaId |
number | Filtrar por analista |
orgaoId |
number | Filtrar por órgão |
portalId |
number | Filtrar por portal |
tipoId |
number | Filtrar por tipo |
dataInicio |
date | Data de início (range) |
dataFim |
date | Data de fim (range) |
municipio |
string | Filtrar por município |
uf |
string | Filtrar por UF |
page |
number | Número da página (default: 1) |
limit |
number | Itens por página (default: 10) |
{
"data": [
{
"id": 1,
"numeroCredenciamento": "CRED-2024-001",
"status": "HABILITADOS",
"orgao": {
"id": 1,
"titulo": "Prefeitura Municipal"
},
"analista": {
"id": 2,
"name": "João Silva"
},
"dataLicitacao": "2024-10-20T00:00:00.000Z"
}
],
"meta": {
"total": 45,
"page": 1,
"limit": 10,
"totalPages": 5
}
}
| Método | Endpoint | Descrição | Limite |
|---|---|---|---|
| POST | /anexos/credenciamento/:id |
Upload de arquivo | 10MB |
| GET | /anexos/credenciamento/:id |
Listar anexos | - |
| GET | /anexos/:id/download |
Download de arquivo | - |
| DELETE | /anexos/:id |
Deletar arquivo | - |
POST /anexos/credenciamento/1
Content-Type: multipart/form-data
Authorization: Bearer <token>
file: [arquivo.pdf]
| Método | Endpoint | Descrição |
|---|---|---|
| GET | /users |
Listar usuários |
| GET | /users/:id |
Buscar por ID |
| POST | /users |
Criar usuário |
| PATCH | /users/:id |
Atualizar usuário |
| DELETE | /users/:id |
Deletar usuário |
Endpoints disponíveis para:
/orgaos - Órgãos públicos/portais - Portais de licitação/tipos - Tipos de credenciamento/fornecedores - FornecedoresTodos seguem o padrão: GET, GET/:id, POST, PATCH/:id, DELETE/:id
# Database
DATABASE_URL="mysql://user:pass@host:3306/db_name"
# JWT
JWT_SECRET="sua-chave-secreta-muito-segura"
JWT_EXPIRES_IN="7d"
# Email
EMAIL_HOST="smtp.gmail.com"
EMAIL_PORT=587
EMAIL_USER="email@gmail.com"
EMAIL_PASS="senha-app"
EMAIL_FROM="Sistema <noreply@sistema.com>"
# Upload
MAX_FILE_SIZE=10485760 # 10MB
VITE_API_URL=https://api.seu-dominio.com
# 1. Gerar Prisma Client
npm run prisma:generate
# 2. Executar migrações
npm run prisma:migrate deploy
# 3. Build do NestJS
npm run build
# 4. Iniciar aplicação
npm run start:prod
# 1. Build para produção
npm run build
# 2. Preview local (opcional)
npm run preview
# 3. Deploy (exemplo Vercel)
vercel --prod
# Criar migração
npm run prisma:migrate dev -- --name nome_da_migracao
# Aplicar migrações (produção)
npm run prisma:migrate deploy
# Abrir Prisma Studio (interface visual)
npm run prisma:studio
# Popular banco com dados iniciais
npm run prisma:seed
# Resetar banco (CUIDADO - apaga dados)
npx prisma migrate reset
Interface visual para gerenciar banco de dados
npm run prisma:studio
# Acesse: http://localhost:5555
# Verificar se MySQL está rodando
docker-compose ps
# Ver logs do MySQL
docker-compose logs mysql
# Reiniciar MySQL
docker-compose restart mysql
Verifique se o backend está com CORS habilitado para a origem do frontend em main.ts:
app.enableCors({
origin: ['http://localhost:3000', 'https://seu-dominio.com'],
credentials: true,
});
Token expirado ou inválido. Faça logout e login novamente.