21 KiB
Design Document
Overview
Sistema inteligente de importação de CSV com interface visual de mapeamento de colunas, sugestão automática baseada em similaridade de strings, memorização de perfis e validação de dados em tempo real.
Architecture
Componentes Principais
┌─────────────────────────────────────────────────────────┐
│ Interface do Usuário │
├─────────────────────────────────────────────────────────┤
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Upload │ │ Mapeamento │ │ Validação │ │
│ │ CSV │ │ Visual │ │ Preview │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
└─────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────┐
│ Motor de Processamento │
├─────────────────────────────────────────────────────────┤
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Parser │ │ Sugestão │ │ Validador │ │
│ │ CSV │ │ Automática │ │ de Dados │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Conversor │ │ Calculador │ │ Categorizador│ │
│ │ Unidades │ │ Fórmulas │ │ Automático │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
└─────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────┐
│ Camada de Persistência │
├─────────────────────────────────────────────────────────┤
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Perfis de │ │ Banco │ │ Metadata │ │
│ │ Importação │ │ de Dados │ │ Importação │ │
│ │ (localStorage)│ │(BANCO_DADOS) │ │(localStorage)│ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
└─────────────────────────────────────────────────────────┘
Components and Interfaces
1. CSVParser
Responsabilidade: Ler e parsear arquivos CSV
class CSVParser {
/**
* Parseia arquivo CSV e retorna estrutura de dados
* @param {File} file - Arquivo CSV
* @returns {Promise<ParsedCSV>}
*/
async parse(file) {
// Detecta encoding (UTF-8, ISO-8859-1)
// Detecta delimitador (vírgula, ponto-e-vírgula, tab)
// Parseia linhas e colunas
// Retorna { headers, rows, metadata }
}
/**
* Detecta tipos de dados de cada coluna
* @param {Array} rows - Linhas de dados
* @returns {Object} - Mapa coluna -> tipo
*/
detectColumnTypes(rows) {
// Analisa valores e infere tipo (number, string, date)
}
}
2. ColumnMapper
Responsabilidade: Gerenciar mapeamento de colunas
class ColumnMapper {
/**
* Sugere mapeamento automático baseado em similaridade
* @param {Array} csvHeaders - Cabeçalhos do CSV
* @param {Array} systemFields - Campos do sistema
* @returns {Object} - Mapa sugerido
*/
suggestMapping(csvHeaders, systemFields) {
// Usa algoritmo de similaridade (Levenshtein)
// Considera sinônimos
// Retorna mapeamento sugerido
}
/**
* Valida mapeamento
* @param {Object} mapping - Mapeamento atual
* @returns {ValidationResult}
*/
validateMapping(mapping) {
// Verifica campos obrigatórios
// Verifica tipos compatíveis
// Retorna erros e avisos
}
}
3. ImportProfile
Responsabilidade: Gerenciar perfis de importação salvos
class ImportProfile {
/**
* Salva perfil de importação
* @param {string} materialType - Tipo de material
* @param {Object} profile - Configuração do perfil
*/
save(materialType, profile) {
// Salva no localStorage
// Inclui: mapeamento, conversões, regras
}
/**
* Carrega perfil salvo
* @param {string} materialType - Tipo de material
* @returns {Object|null} - Perfil ou null
*/
load(materialType) {
// Carrega do localStorage
}
/**
* Lista todos os perfis
* @returns {Array} - Lista de perfis
*/
listAll() {
// Retorna todos os perfis salvos
}
}
4. DataValidator
Responsabilidade: Validar dados antes da importação
class DataValidator {
/**
* Valida linha de dados
* @param {Object} row - Linha de dados
* @param {Object} schema - Schema esperado
* @returns {ValidationResult}
*/
validateRow(row, schema) {
// Valida tipos
// Valida ranges (min/max)
// Valida campos obrigatórios
// Retorna erros específicos
}
/**
* Valida lote de dados
* @param {Array} rows - Linhas de dados
* @param {Object} schema - Schema esperado
* @returns {BatchValidationResult}
*/
validateBatch(rows, schema) {
// Valida todas as linhas
// Retorna estatísticas (válidas, inválidas)
// Retorna lista de erros por linha
}
}
5. UnitConverter
Responsabilidade: Converter unidades de medida
class UnitConverter {
/**
* Converte valor entre unidades
* @param {number} value - Valor a converter
* @param {string} fromUnit - Unidade origem
* @param {string} toUnit - Unidade destino
* @returns {number} - Valor convertido
*/
convert(value, fromUnit, toUnit) {
// Tabela de conversões
// Aplica fator de conversão
}
/**
* Detecta unidade de uma coluna
* @param {Array} values - Valores da coluna
* @param {string} columnName - Nome da coluna
* @returns {string|null} - Unidade detectada
*/
detectUnit(values, columnName) {
// Analisa nome da coluna
// Analisa range de valores
// Retorna unidade provável
}
}
6. FormulaCalculator
Responsabilidade: Calcular campos derivados
class FormulaCalculator {
/**
* Avalia fórmula
* @param {string} formula - Fórmula a avaliar
* @param {Object} context - Contexto com valores
* @returns {number} - Resultado
*/
evaluate(formula, context) {
// Parseia fórmula
// Valida sintaxe
// Calcula resultado
}
/**
* Valida fórmula
* @param {string} formula - Fórmula a validar
* @param {Array} availableFields - Campos disponíveis
* @returns {ValidationResult}
*/
validateFormula(formula, availableFields) {
// Verifica sintaxe
// Verifica campos existem
// Retorna erros
}
}
7. AutoCategorizer
Responsabilidade: Categorizar itens automaticamente
class AutoCategorizer {
/**
* Aplica regras de categorização
* @param {Object} item - Item a categorizar
* @param {Array} rules - Regras de categorização
* @returns {string} - Categoria atribuída
*/
categorize(item, rules) {
// Avalia cada regra em ordem
// Retorna primeira categoria que match
// Retorna "Sem Categoria" se nenhuma match
}
/**
* Cria regra de categorização
* @param {Object} ruleConfig - Configuração da regra
* @returns {Rule}
*/
createRule(ruleConfig) {
// Cria regra com condições
// Suporta: >, <, =, !=, contains, range
}
}
Data Models
ParsedCSV
{
headers: ['coluna1', 'coluna2', ...],
rows: [
{ coluna1: 'valor1', coluna2: 'valor2', ... },
...
],
metadata: {
encoding: 'UTF-8',
delimiter: ',',
rowCount: 100,
columnTypes: {
coluna1: 'string',
coluna2: 'number',
...
}
}
}
ImportProfile
{
id: 'perfis_hp_v1',
materialType: 'perfis_hp',
name: 'Perfis HP - Usiminas',
createdAt: '2025-11-09T...',
updatedAt: '2025-11-09T...',
mapping: {
'altura_mm': 'Altura (mm)',
'aba_mm': 'Largura Aba',
'peso_kg_m': 'Peso Linear',
...
},
conversions: {
'altura_mm': { from: 'mm', to: 'mm' },
'peso_kg_m': { from: 'lb/ft', to: 'kg/m', factor: 1.488 },
...
},
calculatedFields: {
'area_cm2': {
formula: 'peso_kg_m / 0.00785',
description: 'Área calculada a partir do peso'
}
},
categorizationRules: [
{
condition: 'altura_mm < 150',
category: 'Pequeno'
},
{
condition: 'altura_mm >= 150 AND altura_mm < 250',
category: 'Médio'
},
...
],
requiredFields: ['nome', 'altura_mm', 'peso_kg_m'],
optionalFields: ['momento_inercia_xx_cm4', ...]
}
ValidationResult
{
valid: true/false,
errors: [
{
row: 5,
field: 'peso_kg_m',
message: 'Valor deve ser numérico',
value: 'abc'
},
...
],
warnings: [
{
row: 10,
field: 'area_cm2',
message: 'Valor fora do range esperado',
value: 1000
},
...
],
statistics: {
totalRows: 100,
validRows: 95,
invalidRows: 5,
warningRows: 10
}
}
Error Handling
Tipos de Erro
-
ParseError: Erro ao ler CSV
- Encoding inválido
- Formato corrompido
- Delimitador não detectado
-
MappingError: Erro no mapeamento
- Campo obrigatório não mapeado
- Tipo incompatível
- Coluna não encontrada
-
ValidationError: Erro na validação
- Tipo de dado incorreto
- Valor fora do range
- Campo obrigatório vazio
-
ConversionError: Erro na conversão
- Unidade não suportada
- Valor não conversível
- Fator de conversão inválido
Estratégia de Tratamento
try {
// Processar importação
} catch (error) {
if (error instanceof ParseError) {
// Mostrar erro de parsing
// Sugerir verificar formato do arquivo
} else if (error instanceof MappingError) {
// Destacar campos problemáticos
// Permitir correção no mapeamento
} else if (error instanceof ValidationError) {
// Mostrar linhas com erro
// Permitir importar apenas válidas
} else if (error instanceof ConversionError) {
// Mostrar erro de conversão
// Permitir ajustar configuração
}
}
Testing Strategy
Testes Unitários
-
CSVParser
- Testar parsing de diferentes formatos
- Testar detecção de encoding
- Testar detecção de tipos
-
ColumnMapper
- Testar sugestão de mapeamento
- Testar validação de mapeamento
- Testar similaridade de strings
-
DataValidator
- Testar validação de tipos
- Testar validação de ranges
- Testar campos obrigatórios
-
UnitConverter
- Testar conversões conhecidas
- Testar detecção de unidades
- Testar erros de conversão
Testes de Integração
-
Fluxo Completo de Importação
- Upload → Mapeamento → Validação → Importação
- Testar com CSVs reais
- Testar com perfis salvos
-
Importação em Lote
- Múltiplos arquivos
- Diferentes tipos de materiais
- Relatório consolidado
Testes de Interface
-
Drag & Drop de Colunas
- Arrastar coluna CSV para campo
- Visual feedback
- Desfazer mapeamento
-
Preview de Dados
- Mostrar valores originais
- Mostrar valores convertidos
- Mostrar valores calculados
-
Validação em Tempo Real
- Destacar erros
- Mostrar estatísticas
- Atualizar ao modificar mapeamento
Interface Design
Tela Principal de Importação
┌─────────────────────────────────────────────────────────────┐
│ 📥 Importador Inteligente de CSV │
├─────────────────────────────────────────────────────────────┤
│ │
│ 1️⃣ Selecionar Arquivo │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 📁 Escolher CSV... │ │
│ │ ✅ tubos_rhs_fornecedor_x.csv (35 linhas, 15 cols) │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ 2️⃣ Tipo de Material │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ [Dropdown: Tubos RHS ▼] │ │
│ │ 💾 Perfil salvo encontrado: "Fornecedor X" │ │
│ │ [Usar Perfil] [Criar Novo] │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ 3️⃣ Mapeamento de Colunas │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ CSV → Sistema │ │
│ │ ───────────────────────────────────────────────── │ │
│ │ 📊 "Largura (mm)" → largura_mm ✅ │ │
│ │ 📊 "Altura (mm)" → altura_mm ✅ │ │
│ │ 📊 "Espessura" → espessura_mm ✅ │ │
│ │ 📊 "Peso Linear" → peso_kg_m ✅ │ │
│ │ 🔄 Converter: lb/ft → kg/m │ │
│ │ 📊 "Aplicação" → aplicacao ✅ │ │
│ │ 📊 "Coluna Extra" → [Ignorar] ⚠️ │ │
│ │ │ │
│ │ ⚠️ Campo obrigatório não mapeado: tipo │ │
│ │ 💡 Sugestão: Criar regra de categorização │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ 4️⃣ Preview e Validação │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 📊 Estatísticas: │ │
│ │ • Total: 35 linhas │ │
│ │ • Válidas: 33 ✅ │ │
│ │ • Com erro: 2 ❌ │ │
│ │ • Com aviso: 5 ⚠️ │ │
│ │ │ │
│ │ [Ver Erros] [Ver Preview] │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ [Cancelar] [💾 Salvar Perfil] [📥 Importar Dados] │
└─────────────────────────────────────────────────────────────┘
Modal de Mapeamento Visual
┌─────────────────────────────────────────────────────────────┐
│ 🎯 Mapeamento Visual de Colunas │
├─────────────────────────────────────────────────────────────┤
│ │
│ Arraste as colunas do CSV para os campos do sistema │
│ │
│ ┌──────────────────┐ ┌──────────────────┐ │
│ │ Colunas CSV │ │ Campos Sistema │ │
│ ├──────────────────┤ ├──────────────────┤ │
│ │ 📊 Largura │────────→│ ✅ largura_mm │ │
│ │ 📊 Altura │────────→│ ✅ altura_mm │ │
│ │ 📊 Espessura │────────→│ ✅ espessura_mm │ │
│ │ 📊 Peso Linear │────────→│ ✅ peso_kg_m │ │
│ │ 📊 Aplicação │────────→│ ✅ aplicacao │ │
│ │ 📊 Coluna Extra │ │ ⚠️ tipo │ │
│ │ │ │ (obrigatório) │ │
│ └──────────────────┘ └──────────────────┘ │
│ │
│ 💡 Dica: Clique em "Sugerir Automático" para mapear │
│ │
│ [Sugerir Automático] [Limpar Tudo] [Confirmar] │
└─────────────────────────────────────────────────────────────┘
Performance Considerations
-
Parsing de CSV Grande
- Usar Web Workers para não bloquear UI
- Processar em chunks de 1000 linhas
- Mostrar progresso
-
Validação em Tempo Real
- Debounce de 300ms ao modificar mapeamento
- Validar apenas primeiras 100 linhas para preview
- Validação completa apenas ao importar
-
Armazenamento de Perfis
- Comprimir perfis grandes (>100KB)
- Limitar a 50 perfis salvos
- Limpar perfis não usados há >6 meses
-
Importação em Lote
- Processar arquivos em paralelo (máx 3)
- Usar IndexedDB para arquivos >5MB
- Liberar memória após cada arquivo