# Ledir BI — instruções do projeto

Reescrita do dashboard da Ledir Automóveis. O sistema legado (PHP 7.1 + framework
próprio "Beam") fica em `../ledir-dashboard` e continua **em produção rodando em
paralelo** — nunca alterar nada lá sem pedido explícito.

O `README.md` descreve stack, setup e roadmap. Este arquivo descreve **como trabalhar
aqui**.

## Contexto que não está no código

O legado foi auditado em 2026-08-03 e revisado em 2026-09-15. Os achados que
condicionam este projeto:

- **Ele tem erros de cálculo reais**: as duas telas "Mensal" mostram lucros
  diferentes para o mesmo mês (ago/2026: R$ 153.176 e R$ 116.717, contra R$ 130.427
  pelas regras). Nunca portar fórmula do legado por transcrição: recalcular pelas
  regras e conferir contra o CSV de origem.
- **As regras de negócio foram decididas pelo dono em 15/09/2026** e vivem no código:
  `RegraCustoSeeder` (o que entra no custo, por centro × categoria) e as constantes
  de `MigrarLegado` (filial dos vendedores, grafias do dono, retornos corrigidos).
- **Lançamentos "repetidos" NÃO são duplicatas.** Os ~4.250 com mesmo dia, centro,
  categoria, marcador e valor foram conferidos contra os 167 CSVs de origem: são
  títulos distintos. Deduplicar por essa chave apagaria R$ 13,8 milhões reais.
- **Uma venda é uma linha**, quantos financiamentos tiver: a origem emite uma linha
  por financiamento, e `veiculos.chave_venda` é única.
- **O banco tem defeitos medidos.** 20 linhas com colunas deslocadas por parser de CSV
  quebrado (`data_quitacao = '0000-00-00'`) e 31 veículos com `PR?PRIO` (acento
  perdido num import de maio/2025). O resto do "encoding corrompido" era o cliente
  `mysql` exibindo UTF-8 como latin1.
- **O dataset é minúsculo:** ~6 MB no total (47,8 mil lançamentos, 3,7 mil veículos).
  A lentidão do legado é arquitetural, não de escala.
- **Os CSVs da origem não têm contrato fixo.** Nos 167 arquivos reais há 5 layouts de
  lançamentos e 2 de veículos, sem cabeçalho, dois em Windows-1252 e um com datas do
  Excel; o mesmo título muda de texto entre exports. `ArquivoCsv` detecta tudo pelo
  conteúdo e a importação só é considerada certa quando os 167 passam. A pasta de
  arquivos **não** reproduz o histórico do legado (faltam meses, faltam retornos):
  o histórico vem de `etl:legado`, a importação é para meses novos.

## Regras deste repositório

1. **Dinheiro é `decimal(15,2)`.** Nunca `float`/`double`. Nunca somar dinheiro em
   laço PHP.
2. **Agregação em SQL** (`SUM` + `GROUP BY`), nunca em PHP. Se a consulta ficar difícil
   de expressar, o problema é a modelagem, não o SQL.
3. **Nada de cache, fila, Redis ou tabela de agregados** sem uma medição que justifique.
   O volume não pede — adicionar isso é complexidade sem retorno.
4. **Filtro vive na URL** (`#[Url]` do Livewire). Foi o maior problema de UX do legado.
5. **Testes rodam em MySQL**, não em SQLite. Agregação com função de data tem semântica
   diferente entre os dois: verde no SQLite não prova nada.
6. **A conexão `legacy` é somente leitura.** Só comandos de ETL e de golden master a
   usam. Nenhum Model, nenhuma migration.
7. **Leads/CRM está fora de escopo.** Não migrar `leads`, `comentarios`,
   `lead_origem`, `lead_motivo`, `lead_temperatura`, `cidade`, `estado`.

## Antes de considerar um relatório pronto

Todo relatório precisa ser conferido contra o golden master (Fase 3) — os números do
legado capturados mês a mês antes da reescrita. **Divergência não é automaticamente
bug novo**: pode ser erro antigo sendo corrigido. Cada diferença precisa ser
classificada e registrada como *"bug antigo corrigido"* ou *"regressão minha"*. Sem
esse registro não há como defender um número quando o gestor perguntar por que mudou.

## Verificação

```bash
./vendor/bin/pest              # requer php8.3-mysql e MySQL de pé
./vendor/bin/pint              # formatação
./vendor/bin/phpstan analyse   # Larastan nível 6
```

Os três precisam passar antes de commitar.
