Files
SteelBase/.trae/documents/sistema-persistencia-dados.md

18 KiB

🗄️ Sistema de Persistência de Dados - Aço Calc Pro

📋 Visão Geral

Este documento técnico descreve a arquitetura completa do sistema de persistência de dados do Aço Calc Pro, garantindo que todas as personalizações e configurações do painel administrativo permaneçam inalteradas durante o uso e recarregamento do aplicativo.

🏗️ Arquitetura Atual de Persistência

1. Camadas de Armazenamento

graph TD
    A[Aplicação] --> B[State Manager]
    B --> C[Storage Layer]
    C --> D[localStorage]
    C --> E[IndexedDB]
    C --> F[Cache Manager]
    
    subgraph "Persistência Local"
        D
        E
        F
    end
    
    G[Admin Panel] --> H[Data Manager]
    H --> C
    I[User Preferences] --> C

2. Componentes Principais

Data Manager (js/database/data-manager.js)

  • Função: Gerenciamento central de dados e cache inteligente
  • Armazenamento: localStorage com prefixo acoCalcPro_cache_
  • TTL: 24 horas para atualização automática
  • Versionamento: Detecta mudanças e atualiza automaticamente
// Estrutura de cache
localStorage.setItem('acoCalcPro_cache_cantoneiras', JSON.stringify(dados));
localStorage.setItem('acoCalcPro_metadata', JSON.stringify(metadata));

Storage Manager (js/core/storage.js)

  • Função: Gerenciamento de preferências do usuário
  • Armazenamento: localStorage com chave acoCalcPreferences
  • Dados: tema, esquema de cores, tamanho de fonte, família de fonte
// Estrutura de preferências
const userPreferences = {
    theme: 'dark',
    colorScheme: 'default',
    fontSize: 'medium',
    fontFamily: 'default'
};

Cache Manager (js/core/cache-manager.js)

  • Função: Gerenciamento avançado com IndexedDB
  • Armazenamento: IndexedDB para grandes volumes de dados
  • Fallback: CSV embutido quando IndexedDB não disponível
  • Stores: cantoneiras, barras, tubos, perfis, etc.

State Manager (js/core/state.js)

  • Função: Estado global da aplicação
  • Dados: histórico, favoritos, orçamento, seção atual
  • Persistência: Integrado com Storage Manager

Admin Panel (js/database/admin-panel.js)

  • Função: Interface de administração e configurações
  • Estado: Não persiste configurações atualmente
  • Ações: Atualizar dados, limpar cache, exportar/importar

🔍 Análise de Persistência Atual

Pontos Fortes

  1. Cache Inteligente: Dados carregados uma vez, reusados múltiplas vezes
  2. Versionamento Automático: Detecta e aplica atualizações
  3. Multipla Camadas: localStorage, IndexedDB e CSV como fallback
  4. Performance Otimizada: Carregamento rápido após primeiro acesso

Pontos de Fragilidade

  1. Admin Panel Sem Persistência: Configurações administrativas não são salvas
  2. Dependência de localStorage: Limitado a ~5-10MB
  3. Sem Sincronização: Sem backup em nuvem ou sincronização entre dispositivos
  4. Falta de Migração: Sem sistema de migração de dados entre versões

🎯 Proposta de Arquitetura Robustas

1. Sistema de Configurações Persistentes

// Novo sistema de configurações administrativas
class AdminConfigManager {
    constructor() {
        this.configKey = 'acoCalcPro_admin_config';
        this.version = '1.0.0';
        this.defaultConfig = {
            appName: 'AÇO CALC PRO',
            appSubtitle: 'Plataforma Técnica com Base de Dados de Materiais Brasileiros',
            footerText: '© 2025 AÇO CALC PRO v7.5 PROFESSIONAL EDITION',
            themeDefault: 'escuro',
            modeDefault: 'simples',
            toolsVisibility: {
                'cev': true,
                'seletor': true,
                'equivalencias': false,
                'comparativo': false,
                'parafusos': true,
                'layout': true,
                // ... todas as ferramentas
            },
            dataRefreshInterval: 24, // horas
            autoBackup: true,
            backupInterval: 7, // dias
            lastBackup: null,
            version: this.version
        };
    }
    
    saveConfig(config) {
        const configToSave = { ...this.getConfig(), ...config, version: this.version };
        localStorage.setItem(this.configKey, JSON.stringify(configToSave));
        return configToSave;
    }
    
    getConfig() {
        try {
            const saved = localStorage.getItem(this.configKey);
            return saved ? JSON.parse(saved) : this.defaultConfig;
        } catch {
            return this.defaultConfig;
        }
    }
    
    resetConfig() {
        localStorage.setItem(this.configKey, JSON.stringify(this.defaultConfig));
        return this.defaultConfig;
    }
}

2. Sistema de Backup e Restauração

class BackupManager {
    constructor() {
        this.backupKey = 'acoCalcPro_backup';
        this.maxBackups = 5;
    }
    
    async createBackup() {
        const backup = {
            timestamp: Date.now(),
            version: '1.0.0',
            data: {
                preferences: this.getPreferences(),
                adminConfig: this.getAdminConfig(),
                cacheStats: window.dataManager.getCacheStats(),
                appState: this.getAppState()
            }
        };
        
        // Salvar em localStorage
        const backups = this.getBackups();
        backups.unshift(backup);
        
        // Limitar número de backups
        if (backups.length > this.maxBackups) {
            backups.splice(this.maxBackups);
        }
        
        localStorage.setItem(this.backupKey, JSON.stringify(backups));
        return backup;
    }
    
    getBackups() {
        try {
            const saved = localStorage.getItem(this.backupKey);
            return saved ? JSON.parse(saved) : [];
        } catch {
            return [];
        }
    }
    
    restoreBackup(backup) {
        // Restaurar preferências
        if (backup.data.preferences) {
            localStorage.setItem('acoCalcPreferences', JSON.stringify(backup.data.preferences));
        }
        
        // Restaurar configurações admin
        if (backup.data.adminConfig) {
            localStorage.setItem('acoCalcPro_admin_config', JSON.stringify(backup.data.adminConfig));
        }
        
        // Aplicar mudanças
        this.applyRestoredSettings();
        return true;
    }
}

3. Sistema de Migração de Dados

class MigrationManager {
    constructor() {
        this.migrationKey = 'acoCalcPro_migration_version';
        this.currentVersion = '1.0.0';
    }
    
    checkAndRunMigrations() {
        const savedVersion = localStorage.getItem(this.migrationKey) || '0.0.0';
        
        if (savedVersion < this.currentVersion) {
            console.log(`🔄 Executando migração de ${savedVersion} para ${this.currentVersion}`);
            this.runMigrations(savedVersion);
            localStorage.setItem(this.migrationKey, this.currentVersion);
        }
    }
    
    runMigrations(fromVersion) {
        // Migrar de versões antigas
        if (fromVersion < '1.0.0') {
            this.migrateToV1();
        }
    }
    
    migrateToV1() {
        // Converter configurações antigas
        const oldConfig = localStorage.getItem('acoCalcPro_config');
        if (oldConfig) {
            try {
                const parsed = JSON.parse(oldConfig);
                // Converter para novo formato
                const newConfig = this.convertToNewFormat(parsed);
                localStorage.setItem('acoCalcPro_admin_config', JSON.stringify(newConfig));
                localStorage.removeItem('acoCalcPro_config');
            } catch (e) {
                console.warn('⚠️ Falha ao migrar configurações antigas');
            }
        }
    }
}

4. Integração com Admin Panel

// Atualizar admin-panel.js para persistir configurações
function abrirPainelDados() {
    const adminConfig = window.adminConfigManager.getConfig();
    const stats = window.dataManager.getCacheStats();
    
    // Adicionar seções de configuração no modal
    const configSection = `
        <div class="card" style="background: var(--color-bg-1); margin-bottom: 20px;">
            <h3 style="color: var(--color-primary); margin: 0 0 16px 0;">⚙️ Configurações do Sistema</h3>
            <div style="display: grid; gap: 12px;">
                <div>
                    <label>Nome do Aplicativo:</label>
                    <input type="text" id="admin-app-name" value="${adminConfig.appName}" 
                           onchange="salvarConfigAdmin('appName', this.value)">
                </div>
                <div>
                    <label>Tema Padrão:</label>
                    <select id="admin-theme-default" onchange="salvarConfigAdmin('themeDefault', this.value)">
                        <option value="escuro" ${adminConfig.themeDefault === 'escuro' ? 'selected' : ''}>Escuro</option>
                        <option value="claro" ${adminConfig.themeDefault === 'claro' ? 'selected' : ''}>Claro</option>
                    </select>
                </div>
                <div>
                    <label>Intervalo de Atualização (horas):</label>
                    <input type="number" id="admin-refresh-interval" value="${adminConfig.dataRefreshInterval}" 
                           onchange="salvarConfigAdmin('dataRefreshInterval', parseInt(this.value))">
                </div>
                <div>
                    <label>
                        <input type="checkbox" ${adminConfig.autoBackup ? 'checked' : ''} 
                               onchange="salvarConfigAdmin('autoBackup', this.checked)">
                        Auto Backup
                    </label>
                </div>
            </div>
        </div>
        
        <div class="card" style="background: var(--color-bg-1); margin-bottom: 20px;">
            <h3 style="color: var(--color-primary); margin: 0 0 16px 0;">🛠️ Visibilidade de Ferramentas</h3>
            <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 8px;">
                ${Object.entries(adminConfig.toolsVisibility).map(([tool, visible]) => `
                    <label style="display: flex; align-items: center; gap: 8px;">
                        <input type="checkbox" ${visible ? 'checked' : ''} 
                               onchange="salvarConfigAdminTool('${tool}', this.checked)">
                        ${tool}
                    </label>
                `).join('')}
            </div>
        </div>
        
        <div class="card" style="background: var(--color-bg-1); margin-bottom: 20px;">
            <h3 style="color: var(--color-primary); margin: 0 0 16px 0;">💾 Backup e Restauração</h3>
            <div style="display: flex; gap: 12px; flex-wrap: wrap;">
                <button class="btn btn-success" onclick="criarBackup()">
                    📥 Criar Backup
                </button>
                <button class="btn btn-warning" onclick="restaurarUltimoBackup()">
                    📤 Restaurar Último Backup
                </button>
                <button class="btn btn-info" onclick="exportarConfig()">
                    📋 Exportar Configurações
                </button>
                <button class="btn btn-primary" onclick="importarConfig()">
                    📋 Importar Configurações
                </button>
            </div>
        </div>
    `;
    
    // Incluir configSection no modalHTML...
}

// Funções para salvar configurações
function salvarConfigAdmin(chave, valor) {
    const config = window.adminConfigManager.getConfig();
    config[chave] = valor;
    window.adminConfigManager.saveConfig(config);
    console.log(`✅ Config ${chave} salva:`, valor);
}

function salvarConfigAdminTool(tool, visible) {
    const config = window.adminConfigManager.getConfig();
    config.toolsVisibility[tool] = visible;
    window.adminConfigManager.saveConfig(config);
    console.log(`✅ Tool ${tool} visibilidade:`, visible);
    
    // Aplicar mudança imediatamente na UI
    aplicarVisibilidadeFerramentas();
}

🔄 Fluxo Completo de Persistência

sequenceDiagram
    participant User
    participant AdminPanel
    participant AdminConfig
    participant Storage
    participant Backup
    participant App
    
    User->>AdminPanel: Abre configurações
    AdminPanel->>AdminConfig: Carrega config atual
    AdminConfig->>Storage: Lê localStorage
    Storage-->>AdminConfig: Config salva
    AdminConfig-->>AdminPanel: Config atual
    AdminPanel-->>User: Mostra interface
    
    User->>AdminPanel: Altera config
    AdminPanel->>AdminConfig: Salva nova config
    AdminConfig->>Storage: Atualiza localStorage
    AdminConfig-->>AdminPanel: Confirmação
    AdminPanel-->>App: Aplica mudanças
    App-->>User: Interface atualizada
    
    AdminConfig->>Backup: Cria backup automático
    Backup->>Storage: Salva histórico
    
    Note over User,Storage: Em caso de reload...
    App->>AdminConfig: Carrega config salva
    AdminConfig->>Storage: Lê persistência
    Storage-->>AdminConfig: Config intacta
    AdminConfig-->>App: Aplica config
    App-->>User: Estado restaurado

📊 Monitoramento e Debugging

Sistema de Logs Persistente

class PersistentLogger {
    constructor() {
        this.logKey = 'acoCalcPro_logs';
        this.maxLogs = 100;
    }
    
    log(level, message, data = null) {
        const logs = this.getLogs();
        const entry = {
            timestamp: Date.now(),
            level,
            message,
            data,
            userAgent: navigator.userAgent
        };
        
        logs.unshift(entry);
        if (logs.length > this.maxLogs) {
            logs.splice(this.maxLogs);
        }
        
        localStorage.setItem(this.logKey, JSON.stringify(logs));
        
        // Também log no console
        console[level] || console.log(`[${level.toUpperCase()}] ${message}`, data);
    }
    
    getLogs() {
        try {
            const saved = localStorage.getItem(this.logKey);
            return saved ? JSON.parse(saved) : [];
        } catch {
            return [];
        }
    }
    
    exportLogs() {
        const logs = this.getLogs();
        const blob = new Blob([JSON.stringify(logs, null, 2)], { type: 'application/json' });
        const url = URL.createObjectURL(blob);
        const a = document.createElement('a');
        a.href = url;
        a.download = `aco-calc-pro-logs-${Date.now()}.json`;
        a.click();
        URL.revokeObjectURL(url);
    }
}

🛡️ Estratégias de Resiliência

1. Graceful Degradation

  • Sistema funciona mesmo sem localStorage (modo básico)
  • Fallback para CSV quando IndexedDB falhar
  • Mensagens claras para usuário quando recursos não disponíveis

2. Validação e Sanitização

  • Validação de dados antes de salvar
  • Sanitização de inputs do admin
  • Verificação de integridade ao carregar

3. Limite de Armazenamento

  • Monitoramento de uso de localStorage
  • Limpeza automática de dados antigos
  • Compressão de dados grandes

4. Recuperação de Erros

  • Try-catch em todas as operações de I/O
  • Logs detalhados de erros
  • Sistema de recuperação automática

📈 Métricas e Monitoramento

Dashboard de Saúde do Sistema

function getSystemHealth() {
    const health = {
        storage: {
            localStorageAvailable: isStorageAvailable(),
            usage: getStorageUsage(),
            quota: getStorageQuota()
        },
        cache: {
            dataManager: window.dataManager.getCacheStats(),
            indexedDB: window.cacheManager ? window.cacheManager.checkHealth() : null
        },
        config: {
            adminConfig: window.adminConfigManager.getConfig(),
            userPreferences: userPreferences
        },
        timestamp: Date.now()
    };
    
    return health;
}

🚀 Implementação Passo a Passo

Fase 1: Sistema de Configurações (Prioridade Alta)

  1. Criar AdminConfigManager class
  2. Integrar com admin-panel.js
  3. Adicionar UI de configurações no painel
  4. Implementar funções de salvamento/restauração

Fase 2: Sistema de Backup (Prioridade Média)

  1. Criar BackupManager class
  2. Implementar criação automática de backups
  3. Adicionar UI de backup/restauração
  4. Criar sistema de exportação/importação

Fase 3: Sistema de Migração (Prioridade Média)

  1. Criar MigrationManager class
  2. Implementar detecção de versão
  3. Criar scripts de migração
  4. Adicionar rollback em caso de falha

Fase 4: Monitoramento (Prioridade Baixa)

  1. Implementar PersistentLogger
  2. Criar dashboard de saúde
  3. Adicionar alertas de problema
  4. Implementar telemetria anônima

📋 Checklist de Validação

  • Configurações do admin persistem após reload
  • Backup automático funciona corretamente
  • Restauração mantém integridade dos dados
  • Sistema de migração trata versões antigas
  • Logs persistentes ajudam no debugging
  • Dashboard mostra saúde do sistema
  • Fallbacks funcionam quando storage falha
  • UI reflete mudanças imediatamente
  • Performance não é degradada
  • Usuário recebe feedback de ações

🔧 Manutenção e Troubleshooting

Comandos de Diagnóstico

// Verificar integridade do sistema
console.log('Health Check:', getSystemHealth());

// Verificar configurações atuais
console.log('Admin Config:', window.adminConfigManager.getConfig());

// Verificar backups disponíveis
console.log('Backups:', window.backupManager.getBackups());

// Exportar logs para análise
window.persistentLogger.exportLogs();

Procedimentos de Recuperação

  1. Configurações corrompidas: Usar resetConfig()
  2. Cache corrompido: Limpar e recarregar dados
  3. Storage cheio: Limpar logs antigos e backups
  4. Erros críticos: Restaurar último backup válido

Status: Documentação Técnica Completa
Versão: 1.0.0
Data: 2025-01-01
Responsável: Sistema de Documentação Aço Calc Pro