# Mudanças Implementadas: Modelo Read-Only

## Resumo

O sistema foi atualizado para trabalhar com **ERP somente leitura** onde:
- ✅ Podemos LER dados
- ❌ Não podemos escrever/alterar nada no ERP
- ❌ Quando usuário deleta no ERP, é deleção física (dado desaparece)

---

## Arquivos Modificados

### 1. `SincronizacaoERP.php`

#### Mudança 1: Remover busca por data_delecao

**Antes:**
```php
$sql = $sql_origem . " 
    WHERE (data_criacao > '$data_ultima' 
           OR data_modificacao > '$data_ultima'
           OR data_delecao > '$data_ultima')
    ORDER BY data_modificacao DESC";
```

**Depois:**
```php
$sql = $sql_origem . " 
    WHERE (data_criacao > '$data_ultima' 
           OR data_modificacao > '$data_ultima')
    ORDER BY data_modificacao DESC";
```

**Motivo:** Em ERP read-only não procuramos por data_delecao. Deleções serão detectadas na Fase 2.

---

#### Mudança 2: Simplificar processamento (remover DELETE)

**Antes:**
```php
if (!$rast) {
    // NOVO
} elseif ($hash_novo !== $rast['hash_dados']) {
    // MODIFICADO
} elseif ($this->estaDeletedo($registro) && $config['fl_sincronizar_delecoes']) {
    // DELETADO (aqui procurava por soft delete do ERP)
}
```

**Depois:**
```php
if (!$rast) {
    // NOVO
} elseif ($hash_novo !== $rast['hash_dados']) {
    // MODIFICADO
}
// DELETE é detectado na Fase 2, não aqui
```

**Motivo:** Em ERP read-only, não tem como saber se foi deletado a partir dos dados (não existe soft delete). Detectamos por ausência.

---

#### Mudança 3: Adicionar Fase 2 de deteção de deleções

**Método NOVO: `sincronizarDeletadosReadOnly()`**

```php
private function sincronizarDeletadosReadOnly($config) {
    // 1. Buscar TODAS as chaves no ERP (apenas IDs, muito rápido)
    $chaves_erp = [...1.8M chaves...];
    
    // 2. Buscar chaves ativas em rastreamento
    $chaves_rastreadas = [...1.8M chaves...];
    
    // 3. Comparar: quais estavam em rastreamento mas NÃO estão em ERP?
    $chaves_deletadas = array_diff($chaves_rastreadas, $chaves_erp);
    
    // 4. Para cada deletada: adicionar DELETE à fila
    foreach ($chaves_deletadas as $chave) {
        $this->adicionarFila('DELETE', ['chave_origem' => $chave]);
        $stmt->execute("UPDATE rastreamento SET status = 'deletado'");
    }
}
```

**Fluxo:**
```
Fase 1: Buscar novos/modificados (~3-5% do total, ~45K-50K)
Fase 2: Detectar deletados por ausência (~30 min para 1M)
       └─ Buscar todas chaves ERP (20 seg)
       └─ Buscar chaves rastreamento (5 seg)
       └─ array_diff (2-5 seg)
       └─ Adicionar DELETE à fila (~1-2%)
Fase 3: Adicionar à fila
Fase 4: FilaProcessador.php processa
```

---

#### Mudança 4: Remover método antigo

**Deletado:**
```php
private function sincronizarDelecoes($config) {
    // Este procurava por registros já deletados (soft delete no ERP)
    // Não mais necessário no modelo read-only
}
```

---

#### Mudança 5: Remover método `estaDeletedo()`

**Deletado:**
```php
private function estaDeletedo($registro) {
    return !empty($registro['data_delecao']) || 
           (isset($registro['flativo']) && !$registro['flativo']);
}
```

**Motivo:** Não usamos mais este método. Deleções são detectadas por ausência.

---

### 2. `FilaProcessador.php`

#### Mudança: Atualizar método `executarDelete()`

**Antes:**
```php
private function executarDelete($cdintegracao, $dados) {
    $rast = $this->obterRastreamento($cdintegracao, $dados['id_origem']);
    // ...soft delete no HELM...
}
```

**Depois:**
```php
private function executarDelete($cdintegracao, $dados) {
    // DELETE foi detectado por ausência em SincronizacaoERP
    // Aqui apenas executamos o soft delete no HELM
    $rast = $this->obterRastreamento($cdintegracao, $dados['chave_origem'] ?? null);
    // ...soft delete no HELM...
}
```

**Motivo:** A fila agora traz `chave_origem`, não `id_origem`. E o DELETE foi detectado na Fase 2.

---

### 3. `exemplo_integracao.php`

#### Mudança 1: Remover data_delecao do SQL

**Antes:**
```sql
SELECT 
    l.id, l.empresa_id, ...,
    CASE WHEN l.data_delecao IS NOT NULL THEN 1 ELSE 0 END as deletado,
    l.data_delecao
FROM lancamentos
```

**Depois:**
```sql
SELECT 
    l.id, l.empresa_id, ...,
    l.data_criacao, l.data_modificacao
FROM lancamentos
```

**Motivo:** Read-only não tem soft delete no ERP.

---

#### Mudança 2: Simplificar mapearRegistro()

**Antes:**
```php
'flvigente' => !$registro['deletado'],
'dthdelecao' => $registro['data_delecao'],
```

**Depois:**
```php
'flvigente' => true,  // Sempre true em novo INSERT
```

**Motivo:** DELETE é feito pelo FilaProcessador, não trazemos da origem.

---

#### Mudança 3: Simplificar extrairChaveOrigem()

**Antes:**
```php
return md5(
    $registro['cdempresa'] . '|' .
    $registro['nrdocumento'] . '|' .
    $registro['dthlanc']
);
```

**Depois:**
```php
return $registro['id_original'];  // Usar direto o ID do ERP
```

**Motivo:** Chave deve ser simples e rastreável. Se user deleta #26598 no ERP, nós sabemos porque o ID #26598 desapareceu.

---

#### Mudança 4: Adicionar monitoring de deleções

**Novo:**
```php
// Ver deleções detectadas
$qt_deletados = $stmt->fetch(...)['qtregistros'];
if ($qt_deletados > 0) {
    echo "🗑️  " . $qt_deletados . " registros deletados no ERP\n";
}
```

---

## Resumo de Comportamento

### Cenário 1: Novo lançamento #26598 no ERP

```
Sincronizador Fase 1:
  ✓ Encontra #26598 (data_criacao > última_sinc)
  ✓ Calcula hash
  ✓ Verifica rastreamento: não existe
  ✓ Adiciona INSERT à fila
  ✓ RESULTADO: +1 INSERT pendente

FilaProcessador:
  ✓ Processa INSERT
  ✓ Insere lançamento no HELM
  ✓ Registra rastreamento: chave=26598, status='ativo'
  ✓ RESULTADO: lançamento criado ✅
```

---

### Cenário 2: Lançamento #26598 modificado no ERP

```
Sincronizador Fase 1:
  ✓ Encontra #26598 (data_modificacao > última_sinc)
  ✓ Calcula novo hash
  ✓ Verifica rastreamento: EXISTE, hash diferente
  ✓ Adiciona UPDATE à fila
  ✓ RESULTADO: +1 UPDATE pendente

FilaProcessador:
  ✓ Processa UPDATE
  ✓ Atualiza lançamento no HELM
  ✓ Atualiza hash em rastreamento
  ✓ RESULTADO: lançamento atualizado ✅
```

---

### Cenário 3: Lançamento #26598 deletado no ERP

```
Usuário deleta #26598 no ERP (deleção física)

Sincronizador Fase 1:
  ✗ NÃO encontra #26598 (foi deletado)
  ✓ RESULTADO: 0 itens para processar desta forma

Sincronizador Fase 2 (DETECÇÃO DE DELEÇÕES):
  ✓ Busca SELECT id FROM lancamentos no ERP: [1, 2, ..., mas NÃO 26598]
  ✓ Busca rastreamento onde status='ativo': [1, 2, ..., 26598]
  ✓ array_diff(): chaves_deletadas = [26598]
  ✓ Para cada deletada: adiciona DELETE à fila
  ✓ Marca rastreamento: status='deletado'
  ✓ RESULTADO: +1 DELETE pendente

FilaProcessador:
  ✓ Processa DELETE
  ✓ Soft delete no HELM (flvigente=false)
  ✓ Marca rastreamento como deletado
  ✓ RESULTADO: lançamento soft-deletado ✅
```

---

## Performance

### Fase 1 (Novos/Modificados)
- Query: busca ~45K-50K de ~1.8M (3-5%)
- Tempo: ~5-10 minutos
- Resultado: ~45K INSERTs + ~5K UPDATEs na fila

### Fase 2 (Deteções de deleção)
- Query 1: SELECT id FROM lancamentos (~1.8M)
  - Tempo: ~20-30 seg (apenas ID, sem dados)
- Query 2: SELECT chaves do rastreamento
  - Tempo: ~5-10 seg
- Array diff em PHP: ~2-5 seg
- Total Fase 2: **~40 minutos**

### Total por sincronização
- **~1-2 horas para 1M registros**
- Pode ser paralelizado com múltiplos sincronizadores

---

## Checklist: O que você precisa fazer

- [ ] **Testar com dados reais do seu ERP**
  - Criar ~100 lançamentos no ERP
  - Executar sincronização
  - Verificar que aparecem no HELM
  
- [ ] **Testar deleção**
  - Deletar 10 lançamentos no ERP
  - Executar sincronização Fase 2
  - Verificar que foram soft-deletados no HELM
  
- [ ] **Verificar rastreamento**
  ```sql
  SELECT chave_origem, flstatus, dthdelecao
  FROM integracao_rastreamento
  WHERE cdintegracao = 1
  ORDER BY dthdelecao DESC
  LIMIT 20;
  ```
  
- [ ] **Monitorar fila**
  ```
  php exemplo_integracao.php status
  ```
  
- [ ] **Configurar cron job**
  ```bash
  # Sincronização a cada hora
  0 * * * * /usr/bin/php /path/to/exemplo_integracao.php sincronizar
  
  # Worker a cada 5 minutos
  */5 * * * * /usr/bin/php /path/to/app/classes/FilaProcessador.php
  ```

---

## Referência: Estrutura de dados na fila

Quando um DELETE é adicionado à fila:

```json
{
  "cdregistro_destino": 456,
  "chave_origem": 26598,
  "motivo": "Deletado no ERP"
}
```

Já que o registro foi deletado do ERP, não temos mais acesso aos dados originais. A fila traz apenas o mapa (chave → registro HELM) necessário para fazer o soft delete.

