567 lines
21 KiB
Markdown
567 lines
21 KiB
Markdown
# 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
|
||
|
||
```javascript
|
||
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
|
||
|
||
```javascript
|
||
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
|
||
|
||
```javascript
|
||
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
|
||
|
||
```javascript
|
||
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
|
||
|
||
```javascript
|
||
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
|
||
|
||
```javascript
|
||
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
|
||
|
||
```javascript
|
||
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
|
||
|
||
```javascript
|
||
{
|
||
headers: ['coluna1', 'coluna2', ...],
|
||
rows: [
|
||
{ coluna1: 'valor1', coluna2: 'valor2', ... },
|
||
...
|
||
],
|
||
metadata: {
|
||
encoding: 'UTF-8',
|
||
delimiter: ',',
|
||
rowCount: 100,
|
||
columnTypes: {
|
||
coluna1: 'string',
|
||
coluna2: 'number',
|
||
...
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
### ImportProfile
|
||
|
||
```javascript
|
||
{
|
||
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
|
||
|
||
```javascript
|
||
{
|
||
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
|
||
|
||
1. **ParseError**: Erro ao ler CSV
|
||
- Encoding inválido
|
||
- Formato corrompido
|
||
- Delimitador não detectado
|
||
|
||
2. **MappingError**: Erro no mapeamento
|
||
- Campo obrigatório não mapeado
|
||
- Tipo incompatível
|
||
- Coluna não encontrada
|
||
|
||
3. **ValidationError**: Erro na validação
|
||
- Tipo de dado incorreto
|
||
- Valor fora do range
|
||
- Campo obrigatório vazio
|
||
|
||
4. **ConversionError**: Erro na conversão
|
||
- Unidade não suportada
|
||
- Valor não conversível
|
||
- Fator de conversão inválido
|
||
|
||
### Estratégia de Tratamento
|
||
|
||
```javascript
|
||
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
|
||
|
||
1. **CSVParser**
|
||
- Testar parsing de diferentes formatos
|
||
- Testar detecção de encoding
|
||
- Testar detecção de tipos
|
||
|
||
2. **ColumnMapper**
|
||
- Testar sugestão de mapeamento
|
||
- Testar validação de mapeamento
|
||
- Testar similaridade de strings
|
||
|
||
3. **DataValidator**
|
||
- Testar validação de tipos
|
||
- Testar validação de ranges
|
||
- Testar campos obrigatórios
|
||
|
||
4. **UnitConverter**
|
||
- Testar conversões conhecidas
|
||
- Testar detecção de unidades
|
||
- Testar erros de conversão
|
||
|
||
### Testes de Integração
|
||
|
||
1. **Fluxo Completo de Importação**
|
||
- Upload → Mapeamento → Validação → Importação
|
||
- Testar com CSVs reais
|
||
- Testar com perfis salvos
|
||
|
||
2. **Importação em Lote**
|
||
- Múltiplos arquivos
|
||
- Diferentes tipos de materiais
|
||
- Relatório consolidado
|
||
|
||
### Testes de Interface
|
||
|
||
1. **Drag & Drop de Colunas**
|
||
- Arrastar coluna CSV para campo
|
||
- Visual feedback
|
||
- Desfazer mapeamento
|
||
|
||
2. **Preview de Dados**
|
||
- Mostrar valores originais
|
||
- Mostrar valores convertidos
|
||
- Mostrar valores calculados
|
||
|
||
3. **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
|
||
|
||
1. **Parsing de CSV Grande**
|
||
- Usar Web Workers para não bloquear UI
|
||
- Processar em chunks de 1000 linhas
|
||
- Mostrar progresso
|
||
|
||
2. **Validação em Tempo Real**
|
||
- Debounce de 300ms ao modificar mapeamento
|
||
- Validar apenas primeiras 100 linhas para preview
|
||
- Validação completa apenas ao importar
|
||
|
||
3. **Armazenamento de Perfis**
|
||
- Comprimir perfis grandes (>100KB)
|
||
- Limitar a 50 perfis salvos
|
||
- Limpar perfis não usados há >6 meses
|
||
|
||
4. **Importação em Lote**
|
||
- Processar arquivos em paralelo (máx 3)
|
||
- Usar IndexedDB para arquivos >5MB
|
||
- Liberar memória após cada arquivo
|