Arquitetura

Sistema de Auditoria Centralizado - AgrSis

Data: 2026-02-10 Versão: 1.0 Status: Aprovado para Implementação

Sistema de Auditoria Centralizado - AgrSis

Data: 2026-02-10 Versão: 1.0 Status: Aprovado para Implementação


📋 Visão Geral

Centralizar todo o histórico de eventos de Orders e Proposals em uma única tabela audit_logs, substituindo a abordagem descentralizada atual (order_status_history).

Benefícios

  • Uma única fonte de verdade para todo histórico
  • Componentes reutilizáveis entre Producer, Supplier e Admin
  • Admin com visão global e atualização em tempo real
  • Facilidade de manutenção - um único código para histórico
  • Extensível - fácil adicionar novas entidades no futuro

🏗️ Arquitetura

┌─────────────────────────────────────────────────────────────────────────┐
│                          AUDIT_LOGS (centralizado)                      │
├─────────────────────────────────────────────────────────────────────────┤
│  auditable_type: "App\Models\Order" | "App\Models\Proposal"             │
│  auditable_id: ID da entidade                                           │
│  event: código do evento (ex: "order.created", "proposal.submitted")    │
│  description: texto descritivo em português                             │
│  old_values / new_values: JSON com mudanças                             │
│  metadata: { reason_type, reason_notes, extra_data }                    │
│  user_id: quem fez a ação                                               │
│  user_type: 'producer' | 'supplier' | 'admin' | 'system'                │
│  ip_address, user_agent: rastreabilidade                                │
│  show_in_activity_feed: boolean (para feed de atividades)               │
└─────────────────────────────────────────────────────────────────────────┘
                                   │
         ┌─────────────────────────┼─────────────────────────┐
         ▼                         ▼                         ▼
   Producer Portal           Supplier Portal           Admin Portal
   ┌─────────────┐           ┌─────────────┐           ┌─────────────┐
   │ Order       │           │ Proposal    │           │ Logs        │
   │ Timeline    │           │ Timeline    │           │ (tempo real)│
   │             │           │             │           │             │
   │ - Filtra    │           │ - Filtra    │           │ - Vê TUDO   │
   │   por Order │           │   por       │           │ - Filtros   │
   │ - Eventos   │           │   Proposal  │           │ - Busca     │
   │   do prod.  │           │ - Eventos   │           │             │
   │             │           │   do suppl. │           │ + Order e   │
   │ ANÔNIMO:    │           │             │           │   Proposal  │
   │ não mostra  │           │ ANÔNIMO:    │           │   views     │
   │ supplier    │           │ não mostra  │           │   (anônimo) │
   └─────────────┘           │ producer    │           └─────────────┘
                             └─────────────┘

📊 Mapeamento de Eventos

Eventos de ORDER (Licitação)

EventoCódigoDescrição (Producer)Descrição (Supplier)Visível
Criadaorder.createdLicitação criada-Producer, Admin
Atualizadaorder.updatedLicitação atualizada-Producer, Admin
Publicadaorder.publishedLicitação publicadaNova licitação disponívelTodos
Proposta recebidaorder.proposal_receivedNova proposta recebida-Producer, Admin
Proposta canceladaorder.proposal_cancelledProposta cancelada pelo fornecedor-Producer, Admin
Em análiseorder.in_analysisPrazo encerrado, em análiseLicitação em análiseTodos
Expiradaorder.expiredLicitação expiradaLicitação expiradaTodos
Canceladaorder.cancelledLicitação canceladaLicitação canceladaTodos
Revogadaorder.revokedLicitação revogadaLicitação revogadaTodos
Vencedor selecionadoorder.awardedProposta vencedora selecionada-Producer, Admin
Finalizadaorder.finishedLicitação finalizadaLicitação finalizadaTodos

Eventos de PROPOSAL (Proposta)

EventoCódigoDescrição (Supplier)Descrição (Producer)Visível
Criadaproposal.createdProposta criada-Supplier, Admin
Atualizadaproposal.updatedProposta atualizada-Supplier, Admin
Enviadaproposal.submittedProposta enviadaNova proposta recebidaTodos
Canceladaproposal.cancelledProposta canceladaProposta canceladaTodos
Em análiseproposal.in_analysisSua proposta está em análise-Supplier, Admin
Aprovadaproposal.acceptedParabéns! Proposta aprovadaProposta selecionadaTodos
Rejeitadaproposal.rejectedProposta não selecionada-Supplier, Admin
Perdidaproposal.lostOutra proposta foi selecionada-Supplier, Admin
Expiradaproposal.expiredProposta expirada-Supplier, Admin
Visualizadaproposal.viewed-Proposta visualizadaProducer, Admin
Favoritadaproposal.favorited-Proposta marcada como favoritaProducer, Admin

🔒 Regras de Anonimidade

Producer vendo Orders:

  • Não vê nome do supplier em eventos de proposta
  • Propostas identificadas como "Proposta A", "Proposta B", etc.
  • Apenas após adjudicação vê dados do vencedor

Supplier vendo Proposals:

  • Não vê nome do producer
  • Order identificada pelo número (ex: "Licitação #2026-001")
  • Não vê outras propostas ou seus dados

Admin:

  • Vê tudo, mas respeita anonimidade nas views de Order e Proposal
  • Na view geral de Logs pode ver todos os dados para debug

🗄️ Estrutura do Banco de Dados

Tabela: audit_logs

CREATE TABLE audit_logs (
    id BIGSERIAL PRIMARY KEY,
    
    -- Entidade auditada (polimórfico)
    auditable_type VARCHAR(255) NOT NULL,  -- 'App\Models\Order', 'App\Models\Proposal'
    auditable_id BIGINT NOT NULL,
    
    -- Evento
    event VARCHAR(100) NOT NULL,           -- 'order.created', 'proposal.submitted'
    description TEXT,                       -- Descrição em português
    
    -- Valores (JSON)
    old_values JSONB,                       -- Estado anterior
    new_values JSONB,                       -- Estado novo
    metadata JSONB,                         -- Dados extras (reason_type, reason_notes, etc)
    
    -- Usuário que fez a ação
    user_id BIGINT,                         -- Pode ser NULL (sistema)
    user_type VARCHAR(50),                  -- 'producer', 'supplier', 'admin', 'system'
    
    -- Rastreabilidade
    ip_address VARCHAR(45),
    user_agent TEXT,
    
    -- Controle de exibição
    show_in_activity_feed BOOLEAN DEFAULT TRUE,
    
    -- Timestamp
    created_at TIMESTAMP NOT NULL DEFAULT NOW(),
    
    -- Índices
    CONSTRAINT fk_audit_user FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE SET NULL
);

-- Índices para performance
CREATE INDEX idx_audit_auditable ON audit_logs(auditable_type, auditable_id);
CREATE INDEX idx_audit_event ON audit_logs(event);
CREATE INDEX idx_audit_user ON audit_logs(user_id);
CREATE INDEX idx_audit_created ON audit_logs(created_at DESC);
CREATE INDEX idx_audit_activity_feed ON audit_logs(show_in_activity_feed, created_at DESC);

📁 Estrutura de Arquivos (Backend)

apps/api/
├── app/
│   ├── Enums/
│   │   └── AuditEvent.php              # Enum com todos os eventos
│   │
│   ├── Models/
│   │   └── AuditLog.php                # Model (já existe, atualizar)
│   │
│   ├── Traits/
│   │   └── Auditable.php               # Trait para models
│   │
│   ├── Services/
│   │   └── AuditService.php            # Service para registrar eventos
│   │
│   ├── Http/
│   │   ├── Controllers/Api/
│   │   │   └── AuditController.php     # Endpoints de histórico
│   │   │
│   │   └── Resources/
│   │       └── AuditLogResource.php    # Resource para API
│   │
│   └── Observers/
│       ├── OrderObserver.php           # Observer para Order (atualizar)
│       └── ProposalObserver.php        # Observer para Proposal (criar)
│
└── database/
    └── migrations/
        └── 2026_02_10_create_audit_logs_table.php

📁 Estrutura de Arquivos (Frontend)

apps/shared/                             # Componentes compartilhados
└── components/
    └── audit/
        ├── AuditTimeline.vue           # Timeline genérica reutilizável
        ├── AuditTimelineItem.vue       # Item individual da timeline
        └── AuditEventBadge.vue         # Badge de evento

apps/producer/
└── components/
    └── order/
        └── OrderHistory.vue            # Usa AuditTimeline filtrado por Order

apps/supplier/
└── components/
    └── proposal/
        └── ProposalHistory.vue         # Usa AuditTimeline filtrado por Proposal

apps/admin/
└── pages/
    └── logs/
        └── index.vue                   # View geral de logs (tempo real)
└── components/
    └── audit/
        └── AdminAuditTimeline.vue      # Timeline com mais detalhes

⏱️ Estimativa de Tempo

FaseTarefaTempo
1. Backend - BaseMigration + Model + Enum30 min
2. Backend - TraitAuditable trait30 min
3. Backend - ServiceAuditService30 min
4. Backend - ObserversOrder + Proposal observers45 min
5. Backend - APIEndpoints + Resource30 min
6. Frontend - SharedComponentes base45 min
7. Frontend - ProducerOrderHistory30 min
8. Frontend - SupplierProposalHistory30 min
9. Frontend - AdminLogs page + timeline1h
10. TestesTestar fluxos30 min
11. DeployDeploy produção15 min
TOTAL~6h

🔄 Migração de Dados

Estratégia:

  1. Criar nova tabela audit_logs
  2. Migrar dados de order_status_history para audit_logs
  3. Manter compatibilidade - order_status_history continua funcionando
  4. Deprecar gradualmente - após validação, remover uso antigo

Script de Migração:

// Migrar order_status_history para audit_logs
OrderStatusHistory::chunk(100, function ($histories) {
    foreach ($histories as $history) {
        AuditLog::create([
            'auditable_type' => Order::class,
            'auditable_id' => $history->order_id,
            'event' => 'order.status_changed',
            'description' => $history->getChangeDescription(),
            'old_values' => ['status' => $history->from_status?->value],
            'new_values' => ['status' => $history->to_status->value],
            'metadata' => [
                'reason_type' => $history->reason_type?->value,
                'reason_notes' => $history->reason_notes,
            ],
            'user_id' => $history->changed_by,
            'user_type' => 'producer',
            'ip_address' => $history->ip_address,
            'user_agent' => $history->user_agent,
            'created_at' => $history->created_at,
        ]);
    }
});

📋 Tasks Linear

Epic: Sistema de Auditoria Centralizado

  1. Backend Criar migration e model AuditLog - 30min
    • Labels: Backed-API, Feature
    • Criar tabela audit_logs com todos os campos
    • Atualizar model AuditLog
  2. Backend Criar enum AuditEvent - 15min
    • Labels: Backed-API, Feature
    • Enum com todos os eventos de Order e Proposal
    • Métodos para label, cor, ícone
  3. Backend Criar trait Auditable - 30min
    • Labels: Backed-API, Feature
    • Trait para registrar eventos automaticamente
    • Hooks para created, updated, deleted
  4. Backend Criar AuditService - 30min
    • Labels: Backed-API, Feature
    • Service para registrar eventos customizados
    • Métodos específicos para cada tipo de evento
  5. Backend Criar/atualizar Observers - 45min
    • Labels: Backed-API, Feature
    • OrderObserver: eventos de status, propostas
    • ProposalObserver: eventos de ciclo de vida
  6. Backend Criar endpoints de histórico - 30min
    • Labels: Backed-API, Feature
    • GET /orders/{uuid}/history
    • GET /proposals/{uuid}/history
    • GET /admin/audit-logs (com filtros)
  7. Frontend Criar componentes compartilhados - 45min
    • Labels: Front-Produtor, Front-Fornecedor, Feature
    • AuditTimeline.vue
    • AuditTimelineItem.vue
    • AuditEventBadge.vue
  8. Frontend Atualizar OrderHistory no Producer - 30min
    • Labels: Front-Produtor, Improvement
    • Usar novo componente AuditTimeline
    • Respeitar anonimidade
  9. Frontend Criar ProposalHistory no Supplier - 30min
    • Labels: Front-Fornecedor, Feature
    • Timeline de histórico da proposta
    • Respeitar anonimidade
  10. Frontend Criar página de Logs no Admin - 1h
    • Labels: Backed-API, Feature
    • View geral com todos os logs
    • Filtros por tipo, entidade, período
    • Atualização em tempo real (polling/websocket)
  11. Deploy Migrar dados e deploy - 30min
    • Labels: Backed-API, Improvement
    • Migrar order_status_history
    • Deploy para produção

✅ Checklist de Implementação

  • Migration criada e executada
  • Model AuditLog atualizado
  • Enum AuditEvent criado
  • Trait Auditable implementado
  • AuditService funcionando
  • Observers configurados
  • Endpoints de histórico criados
  • Componentes Vue compartilhados
  • Producer OrderHistory atualizado
  • Supplier ProposalHistory criado
  • Admin Logs page funcionando
  • Dados migrados de order_status_history
  • Testes executados
  • Deploy realizado

Última atualização: 2026-02-10 Autor: Sistema

Copyright © 2026