# Sincronização de Acordos de Clientes

Este documento descreve como funciona e como utilizar o sistema de sincronização automática de acordos de clientes entre as tabelas de origem (CLIENTES.*, FINANCEIRO.*) e a tabela de destino `cotacao_subsidiada_clientes_acordos`.

## Visão Geral

A tabela `cotacao_subsidiada_clientes_acordos` foi inicialmente populada com um script SQL que extrai dados de múltiplas tabelas relacionadas a acordos de clientes. Porém, esses dados podem mudar nas tabelas de origem sem que a tabela de destino seja atualizada.

A solução implementada sincroniza automaticamente esses dados, mas **respeita uma restrição importante**: registros com `porto_destino_id != 1` foram inseridos manualmente e **NÃO são alterados** durante a sincronização.

## Comportamento da Sincronização

### O que é sincronizado?
- **Criação**: Novos acordos adicionados nas tabelas de origem
- **Atualização**: Mudanças nos valores, modalidade ou apelido do cliente
- **Deleção**: Remoção de acordos que foram excluídos nas tabelas de origem

### O que NÃO é alterado?
- Registros com `porto_destino_id != 1` (registros manuais)
- Registros que foram marcados como deletados (soft delete)

## Formas de Executar a Sincronização

### 1. Comando Artisan (Síncrono)

```bash
# Sincronização simples (síncrona)
php artisan acordos:sincronizar

# Com saída detalhada
php artisan acordos:sincronizar --verbose
```

### 2. Endpoint API

#### Sincronização Síncrona (imediata)
```http
POST /api/comercial/importacao/gerencial/cotacoes-subsidiadas/acordos/sincronizar
Authorization: Bearer {token}
```

**Resposta (200 OK):**
```json
{
  "success": true,
  "message": "Sincronização realizada com sucesso",
  "stats": {
    "created": 5,
    "updated": 3,
    "deleted": 1,
    "errors": []
  }
}
```

### 3. Agendamento Automático (Cron)

Para executar a sincronização automaticamente em intervalos, adicione a seguinte linha ao seu `crontab`:

```bash
# Sincronizar a cada 6 horas
0 */6 * * * cd /caminho/para/api-scoa && php artisan acordos:sincronizar >> storage/logs/acordos-sync.log 2>&1

# Ou sincronizar diariamente às 2 da manhã
0 2 * * * cd /caminho/para/api-scoa && php artisan acordos:sincronizar >> storage/logs/acordos-sync.log 2>&1

# Ou sincronizar a cada 30 minutos
*/30 * * * * cd /caminho/para/api-scoa && php artisan acordos:sincronizar >> storage/logs/acordos-sync.log 2>&1
```

## Arquivos Implementados

### Serviço de Sincronização
- **Arquivo**: `app/Services/CotacaoSubsidiadaClienteAcordoSyncService.php`
- **Classe**: `CotacaoSubsidiadaClienteAcordoSyncService`
- **Método Principal**: `sync(): array`
- **Responsabilidade**: Executar a lógica de sincronização

### Comando Artisan
- **Arquivo**: `app/Console/Commands/SincronizarAcordosClientesCommand.php`
- **Comando**: `acordos:sincronizar`
- **Opções**: `--verbose`
- **Responsabilidade**: Interface CLI para sincronização

### Controller
- **Arquivo**: `app/Http/Controllers/Comercial/Importacao/Gerencial/CotacaoSubsidiadaClienteAcordoController.php`
- **Método**: `sincronizar()`
- **Rota**: `POST /api/comercial/importacao/gerencial/cotacoes-subsidiadas/acordos/sincronizar`
- **Responsabilidade**: Endpoint API para sincronização

## Exemplo de Uso Prático

### Cenário 1: Sincronização Manual via CLI

```bash
# O usuário quer sincronizar imediatamente e ver o resultado
cd /var/www/html/api-scoa
php artisan acordos:sincronizar --verbose

# Saída esperada:
# ✓ Sincronização realizada com sucesso!
# 
# Estatísticas:
#   • Criados: 5
#   • Atualizados: 3
#   • Deletados: 1
```

### Scenario 2: Sincronização via API

```bash
# Requisição HTTP
curl -X POST \
  'http://localhost:8080/api/comercial/importacao/gerencial/cotacoes-subsidiadas/acordos/sincronizar' \
  -H 'Authorization: Bearer seu_token_api' \
  -H 'Content-Type: application/json'
```

### Scenario 3: Agendamento Cron (Recomendado para Produção)

```bash
# Editar crontab
crontab -e

# Adicionar a linha:
0 */6 * * * cd /var/www/html/api-scoa && php artisan acordos:sincronizar >> storage/logs/acordos-sync.log 2>&1
```

## Tratamento de Erros

A sincronização é transacional — se ocorrer um erro durante o processo, todas as mudanças são desfeitas (ROLLBACK).

Se há erros individuais durante a sincronização, eles são coletados e reportados:

```json
{
  "success": true,
  "message": "Sincronização realizada com sucesso",
  "stats": {
    "created": 5,
    "updated": 3,
    "deleted": 0,
    "errors": [
      {
        "action": "sync_source",
        "cliente_id": 123,
        "message": "Erro ao processar cliente: ..."
      }
    ]
  }
}
```

Os erros também são registrados em `storage/logs/laravel.log`.

## Monitoramento

### Verificar Logs

```bash
# Logs gerais
tail -f storage/logs/laravel.log

# Logs de sincronização agendada
tail -f storage/logs/acordos-sync.log
```

### Estatísticas da Sincronização

```bash
# Consultar registros criados/modificados recentemente
php artisan tinker

# Dentro do tinker:
>>> DB::table('cotacao_subsidiada_clientes_acordos')
    ->where('porto_destino_id', 1)
    ->where('updated_at', '>=', now()->subHours(6))
    ->count();

>>> DB::table('cotacao_subsidiada_clientes_acordos')
    ->where('porto_destino_id', '!=', 1)
    ->count();  // Registros manuais (não afetados pela sincronização)
```

## Considerações de Performance

- A sincronização lê todas as tabelas de origem e compara com a tabela de destino
- Para grandes volumes de dados, recomenda-se usar a opção `--background` ou agendar em horários de baixa demanda
- A sincronização usa transações para garantir consistência

## Segurança

- O endpoint de sincronização requer autenticação (`auth:api`)
- Apenas usuários autenticados podem sincronizar via API
- O comando Artisan pode ser restringido via permissões do sistema operacional

## Troubleshooting

### Problema: Sincronização não funciona

1. Verifique se o banco de dados está acessível
2. Verifique os logs: `tail -f storage/logs/laravel.log`
3. Teste a conexão com as tabelas de origem: `php artisan tinker`

### Problema: Registros manuais estão sendo alterados

- Verifique que esses registros têm `porto_destino_id != 1`
- A sincronização respeita apenas registros com `porto_destino_id = 1`

## Referências

- Query de origem: Ver em `CotacaoSubsidiadaClienteAcordoSyncService::getSourceData()`
- Modelo: `App\Models\CotacaoSubsidiadaClienteAcordo`
- Controller: `App\Http\Controllers\Comercial\Importacao\Gerencial\CotacaoSubsidiadaClienteAcordoController`
