# Cutover

Roteiro para o Ledir BI substituir o sistema antigo.

O que dá para conferir por código está em `php artisan cutover:verificar` — rode
antes e depois de cada etapa. Aqui fica só o que depende de decisão ou de gente.

O legado **continua no ar** durante todo o processo. Ele não é desligado por
nenhuma etapa deste documento; desligar é a última decisão, e é sua.

---

## Antes da virada

### 1. Decisões de negócio — fechadas em 15/09/2026

Estão no código, não neste documento:

- **O que entra no custo**, por centro de custo × categoria: `RegraCustoSeeder`.
- **O que conta como outra receita**: `App\Regras\OutrasReceitas`, gravado por
  `RegraReceitaSeeder`.
- **Quem é loja e divide o custo GERAL**: `unidades.loja_desde`, no
  `UnidadeSeeder` — duas lojas até agosto/2025, três a partir de setembro.
- **Filial dos vendedores ativos, grafias do dono e correções de dado**:
  constantes de `MigrarLegado`.

O gabarito que prova a implementação é `tests/golden/resultado-regras.csv`.

Ainda útil para revisão de cadastro:

```bash
php artisan revisar:pendencias
```

Gera em `storage/app/revisao/` a lista de vendedores com possível homônimo
(`AGUSTO`/`AUGUSTO`, `LUAN TELLES`/`LUAN FERREIRA TELLES`). As grafias do dono
já foram fundidas.

### 2. Triar a quarentena

```sql
SELECT origem, motivo, COUNT(*) FROM quarentena GROUP BY origem, motivo;
```

São as linhas que não couberam no modelo — 20 quebradas pelo parser do legado,
uma sem marcador (R$ 2.000,00), um veículo sem placa nem chassi. Nenhuma foi
descartada. Decida uma a uma: corrigir na origem e reimportar, ou aceitar a
perda por escrito.

### 3. Cadastrar o time

Em `/usuarios`, com o administrador.

Os 33 usuários do legado **não** são migrados, por dois motivos: as senhas são
`md5` em `varchar(32)`, não convertíveis, e 7 e-mails estão repetidos entre
pessoas diferentes — `thomaz@merkata.com.br` serve a 5 contas, uma delas de
administrador. Migrar automaticamente criaria acesso cruzado.

A lista útil do legado, sem o perfil Marketing/Leads que saiu de escopo:
2 do financeiro e 19 vendedores, dos quais 8 com acesso nos últimos 6 meses.

Cada pessoa recebe a senha inicial de você. Não há envio de e-mail configurado.

### 4. Carga final do histórico

```bash
php artisan etl:legado --forcar
php artisan golden:capturar
```

Rode **depois** da última importação feita no sistema antigo, para que o corte
seja limpo. O `golden:capturar` refeito no mesmo momento garante que a linha de
base e o gabarito pelas regras cubram o mesmo período.

Confira o relatório no fim da saída do ETL: total migrado + quarentena + linhas
fundidas (uma venda por financiamento) tem que fechar com o total da origem.

---

## A virada

### 5. Preparar o ambiente

```bash
cp .env.example .env      # e preencher
php artisan key:generate
php artisan migrate --force
php artisan db:seed --class=UnidadeSeeder --force
php artisan db:seed --class=RegraCustoSeeder --force
php artisan db:seed --class=RegraReceitaSeeder --force
php artisan db:seed --class=AdministradorSeeder --force
php artisan usuario:senha                                 # define a senha
npm ci && npm run build
php artisan config:cache && php artisan route:cache && php artisan view:cache
```

`APP_DEBUG=false` e `APP_ENV=production` são impedimento no verificador, não
recomendação: com debug ligado qualquer erro expõe caminho de arquivo, consulta
e variável de ambiente.

Com `config:cache` ativo, `env()` fora de `config/` devolve `null`. É por isso
que o administrador inicial lê `config/admin.php` e não o ambiente direto.

### 6. Conferir

```bash
php artisan cutover:verificar
```

Nenhum **impedimento** pode restar. Os pontos de **atenção** são decisão
consciente — se sobrar algum, é porque você escolheu que sobrasse.

### 7. Rodar em paralelo

Mantenha os dois sistemas recebendo a mesma importação por **pelo menos um
fechamento mensal completo**. Não é desconfiança do código: é que divergência
só aparece quando alguém compara um número que conhece.

A cada mês em paralelo, compare contra `tests/golden/`. Toda diferença precisa
ser classificada e anotada em `tests/golden/REGISTRO.md` como *bug antigo
corrigido* ou *regressão minha*.

**Já se sabe que estes vão divergir, e por quê:**

| Número | Diferença esperada |
|---|---|
| Resultado mensal e por loja | As duas telas "Mensal" do legado discordam entre si e das regras: em ago/2026 mostram R$ 153.176 e R$ 116.717; pelas regras, R$ 130.426,90. |
| Rateio do GERAL | O legado divide por 2 fixo nos acompanhamentos e por 3 fixo no mensal; o certo é ÷2 até ago/2025 e ÷3 depois. |
| Lucro dos veículos | O legado ora soma o retorno, ora não; pela regra, sempre soma. |
| Vendas de 2019–2020 | 12 linhas do legado eram financiamento de uma venda já contada. |
| Custo total de venda e de operação | O legado erra os cards: lê o mês corrente no lugar do ano anterior, e nove literais de categoria não casam com nada. Os cards ficam, como visão de caixa, com o cálculo corrigido. |
| Visão geral: despesas | O legado soma o marcador cru, com compra de veículo e retirada de sócios; a tela nova mostra as despesas pelas regras, as mesmas do Mensal. |
| Despesas por centro e por unidade | O padrão é o que entra no resultado; "Todas as saídas" reproduz o legado. A tela anual por unidade tem Concórdia, que o legado não tinha. |
| Vendedores e metas | Venda ligada ao cadastro do vendedor, não ao nome escrito; meta mensal, não um ano serializado; sem conversão de leads. |

Divergência fora dessa lista é para investigar antes de aceitar.

---

## Depois

### Importar os meses seguintes

Pela tela `/importacoes` (administrador ou financeiro), ou por
`php artisan importar:csv <arquivos...>`. O arquivo sai do sistema de gestão
como está: sem cabeçalho, em qualquer um dos layouts já usados, em UTF-8 ou
Windows-1252. A tela confere antes de gravar.

- Um lançamento que outro arquivo já trouxe não entra de novo — reexportar o
  mês, ou um export que traz quitações do mês anterior, é seguro.
- Linha nova **parecida** com lançamento de outro arquivo (mesmo favorecido,
  datas e valor, descrição diferente) entra e fica apontada: confira se não é o
  mesmo título editado na origem.
- Lançamento de um mês que veio do legado é **recusado** para a quarentena: o
  legado não guardava favorecido nem descrição, então não há como saber se é
  repetido. Importe só meses posteriores à carga final.

### 8. Desligar o legado

Só depois do paralelo. Na ordem:

1. Tirar a permissão de escrita do sistema antigo — ninguém importa lá por engano.
2. Guardar um dump do banco legado fora do servidor. É a única prova do que os
   números eram antes.
3. Remover `DB_LEGACY_*` do ambiente. O ETL e o `golden:capturar` param de
   funcionar, o que é o esperado: não há mais de onde migrar.
4. Desligar o container.

### 9. O que fica pendente por decisão, não por esquecimento

- **Envio de e-mail** não está configurado (`MAIL_MAILER=log`). Sem ele não há
  "esqueci minha senha" — a redefinição é feita por
  `php artisan usuario:senha <email>`, que pergunta a senha sem exibi-la nem
  deixá-la no histórico do shell.
- **Backup do banco novo** não está automatizado. Precisa existir antes do
  primeiro fechamento que dependa só dele.
- **A coluna Marcador do arquivo de veículos** segue ajustada à mão antes de
  cada importação, por decisão sua. O importador recusa unidade desconhecida em
  vez de inventar uma loja, então esquecer o ajuste falha alto e não corrompe
  nada.
