Appearance
History Module (Audit Log)
Sistema genérico de histórico de alterações para rastrear mudanças em qualquer entidade.
Conceito
Toda alteração (update, mudança de status) grava um snapshot completo da entidade antes da modificação. Isso permite reconstruir o estado da entidade em qualquer ponto no tempo.
Domain Layer
Types (src/domain/history/types.ts)
| Tipo | Descrição |
|---|---|
EntityType | Union de entidades rastreáveis: 'contract' | 'template' | 'workflow' |
HistoryEntry | Registro de histórico com snapshot completo |
HistoryFilter | Filtro por entityType + entityId |
HistoryEntry
| Campo | Tipo | Descrição |
|---|---|---|
id | string | UUID do registro |
entityType | EntityType | Tipo da entidade alterada |
entityId | string | UUID da entidade |
data | string | JSON.stringify do snapshot completo antes da alteração |
updatedBy | string | UUID do usuário que fez a alteração |
updatedAt | Date | Timestamp da alteração |
Constants (src/domain/history/constants.ts)
ENTITY_TYPES: Mapa de entity types disponíveis
API Endpoints
| Método | Endpoint | Descrição |
|---|---|---|
GET | /history?entityType=contract&entityId=:id | Lista histórico de uma entidade (ordenado por data desc) |
POST | /history | Cria entrada de histórico (uso interno) |
GET /history
Query params obrigatórios:
entityType: Tipo da entidade (contract,template,workflow)entityId: UUID da entidade
Response: HistoryEntry[] ordenado por updatedAt desc
POST /history
Body:
json
{
"entityType": "contract",
"entityId": "uuid",
"data": "{...json stringified...}",
"updatedBy": "user-uuid"
}Response: HistoryEntry criado (status 201)
Integração com Entidades
Para adicionar histórico a uma nova entidade:
- Adicionar o tipo em
EntityType(src/domain/history/types.ts) - Adicionar a constante em
ENTITY_TYPES(src/domain/history/constants.ts) - No handler MSW da entidade, importar
addHistoryEntrydesrc/mocks/handlers/history.ts - Antes de aplicar a mutação (PUT/PATCH), chamar:ts
addHistoryEntry('entity-type', entityId, JSON.stringify(currentEntity), userId)
Exemplo (já implementado em contracts)
ts
// src/mocks/handlers/contracts.ts
import { addHistoryEntry } from './history'
// No handler PUT, antes de aplicar as mudanças:
addHistoryEntry('contract', id, JSON.stringify(contracts[index]), userId)Mock Data
Arquivo: src/mocks/data/history.ts
Contém entradas de exemplo para contratos existentes, simulando alterações de status e dados.
Estrutura de Arquivos
src/domain/history/
├── types.ts # HistoryEntry, EntityType, HistoryFilter
├── constants.ts # ENTITY_TYPES
└── index.ts # Re-exports
src/mocks/
├── data/history.ts # Mock data
└── handlers/history.ts # GET/POST handlers + addHistoryEntry helperBackend: Orientações para Implementação
Tabela sugerida: entity_history
| Coluna | Tipo | Constraints |
|---|---|---|
id | UUID | PK, default gen_random_uuid() |
entity_type | VARCHAR(50) | NOT NULL, INDEX |
entity_id | UUID | NOT NULL, INDEX |
data | JSONB | NOT NULL |
updated_by | UUID | NOT NULL, FK → users(id) |
updated_at | TIMESTAMP | NOT NULL, default NOW() |
Índices recomendados
idx_entity_history_lookupem(entity_type, entity_id, updated_at DESC)
Trigger ou middleware
O registro de histórico deve ser criado antes do UPDATE na entidade principal, capturando o estado atual (pré-alteração). Pode ser implementado via:
- Trigger de banco (
BEFORE UPDATE) - Middleware na camada de serviço
- Interceptor no ORM