# Documentação técnica — Módulo de Veículos

Este documento descreve o cadastro de veículos, relações com **eventos**, **pedidos (NF)**, **contratos**, **dashboards de frota** e **gráficos de movimentação**, com base nos controllers, models, Livewire, helpers e views analisados. Detalhamento das rotas `/dashboard/veiculo` e `/dashboard/veiculocusto` (queries com IDs de produto fixos): **`Doc_Modulo_Dashboards.md`** § 5 e § 6.

O uso de **`idveiculo` em eventos** e a flag **`eventotipo.veiculo`** no formulário de agenda admin estão contextualizados em **`Doc_Modulo_Evento.md`**.

---

## 1. Model `Veiculo` (`veiculo`)

| Aspecto | Detalhe |
|---------|---------|
| PK | `idveiculo` |
| Tenant | `TenantScope` global |
| Timestamps | `criadoem` / `alteradoem` |

### 1.1 Campos principais (`$fillable`)

| Campo | Papel |
|-------|--------|
| `idempresa` | Empresa proprietária / contexto |
| `idpessoa` | Responsável (motorista/gestor) — relação `pessoa()` |
| `idcontrato` | Vínculo opcional direto a contrato (`contrato()`) — uso legado/alternativo ao pivô |
| `idseguradora` | Pessoa tipo seguradora (`seguradora()`) |
| `placa`, `marca`, `modelo`, `ano`, `cor`, `sigla` | Identificação e apresentação |
| `tipoveiculo` | Texto livre alinhado às opções do controller (carro, caminhão, etc.) |
| `chassi`, `renavan`, `crv` | Documentação |
| `km` | Hodômetro registrado no **cadastro** do veículo (distinto do `km` por **pedido/NF**) |
| `rastreador`, `apolice`, `datavencimento` | Seguro / rastreamento |
| `status` | Valores usados no admin: **`ATIVO`**, **`INATIVO`** (index exclui `INATIVO` da listagem padrão) |
| `dashboard` | Flag **0/1**: veículo entra com prioridade em ordenações de relatórios de abastecimento/pedidos (`orderBy veiculo.dashboard desc`) |

### 1.2 Relações Eloquent

- `pessoa`, `seguradora`, `empresa` (`HasOne`)
- `pedido()` → `hasMany(Nf::class, 'idveiculo')` — todas as NFs (incluindo pedidos) com esse veículo
- `contratoVeiculo()` → pivô formal contrato–veículo
- `contrato()` → campo `idcontrato` no próprio veículo

### 1.3 Scopes

- `scopeAtivo`: filtra `status = 'Ativo'` (**atenção:** no `VeiculoController` o fluxo usa **`ATIVO`** em maiúsculas; usar o scope pode não bater com os dados reais — inconsistência de convenção no código).
- `scopeWithDashboard`: `dashboard = 1`.

---

## 2. Controller `VeiculoController` (admin)

**Rotas:** `admin/veiculos` (resource), `fetch`, `search` (com `role:ADMIN` na busca).

### 2.1 Dados estáticos na camada HTTP

O controller mantém arrays PHP (não vêm do banco):

- **`$marcas`** — dezenas de marcas (Audi, FIAT, John Deere, etc.)
- **`$tipoveiculo`** — bicicleta, caminhão, carro, máquina, motocicleta, ônibus
- **`$cores`** — paleta nomeada (amarelo, azul, …)

Esses arrays alimentam os selects em `create` / `edit` / `search`.

### 2.2 `index` / `search`

- Eager load: `empresa`, `pessoa`.
- `index`: exclui `veiculo.status = 'INATIVO'`.
- `search`: filtro por `status`, texto em pessoa/empresa/placa/marca/modelo + `filter($request, $query)`.

### 2.3 `store`

- `only([...])` com empresa, pessoa, seguradora, rastreador, documentos, placa, marca, modelo, ano, cor, km, tipo, vencimento, apólice, status.
- **`dashboard`**: `1` se checkbox presente na request, senão `0`.

### 2.4 `edit`

- Lista **`ContratoVeiculo`** onde `idveiculo` = veículo atual (histórico de vínculos contratuais).
- Fornecedores carregados para contexto de apólice/seguro (lista `fornecedor()`).

### 2.5 `update`

- `redirect=true` (padrão): atualiza `dashboard` explicitamente; demais campos via **`$request->except('dashboard')`** (superfície maior que o `only` do ramo JSON).
- `redirect=false`: atualiza apenas whitelist `$veiculoRequest` e retorna JSON com `status`.

### 2.6 `fetch` (datatable JSON) — bugs conhecidos

Algumas colunas foram copiadas de outro módulo e **não** refletem o model `Veiculo`:

- **VENCIMENTO** usa `$venda->datavencimento` em um objeto veículo (atributo inexistente / errado).
- **STATUS** usa `partials.status-switch` com **`id` => `$venda->idnf`** — deveria ser `idveiculo` e status do veículo.

Corrigir antes de confiar na listagem AJAX para operações reais.

### 2.7 `VeiculoRequest`

Existe `app/Http/Requests/Admin/VeiculoRequest.php`, porém o conteúdo atual é de **formulário de contato** (nome, email, captcha), **não** validação de veículo — e o `VeiculoController` **não** injeta esse FormRequest. Na prática, validação é mínima na entrada.

---

## 3. Ligação com Eventos (detalhada)

### 3.1 Dados no banco

- Tabela **`evento`**: coluna **`idveiculo`** (nullable), no `$fillable` do model `Evento`.
- O evento continua vinculado ao **cliente** (`idcliente`), **empresa**, **tipo** (`ideventotipo`), etc.; o veículo é um **recurso opcional** do compromisso.

### 3.2 Tipo de evento (`eventotipo.veiculo`)

No model `EventoTipo`, o campo **`veiculo`** indica se aquele tipo exige ou permite escolha de veículo. Na view `admin/eventos/_form.blade.php`:

- Cada `<option>` de tipo carrega `data-veiculo="{{ $eventoTipo->veiculo }}"`.
- JavaScript lê esse atributo; se **`veiculo === 'SIM'`**, exibe a `div` **`#div-idveiculo`** com o `<select name="idveiculo">`.
- Caso contrário, o bloco permanece oculto (`d-none`).

Ou seja: **não é o veículo que “dispara” evento**; é o **tipo de evento** que define se o formulário mostra o select de frotas.

### 3.3 Fluxo admin de evento

- `EventoController::create` / `edit` carregam **`$veiculos`** (`Veiculo::orderBy('placa')`) e passam à view.
- `store` / `update` usam `$request->all()` (ou tratamento monetário), de modo que **`idveiculo`** segue para o banco quando enviado.
- **Não há** regra adicional no controller que sincronize evento ↔ NF ou pedido só por preencher veículo (ver `Doc_Modulo_Evento.md` / financeiro).

### 3.4 Resumo da relação Evento ↔ Veículo

| Direção | Comportamento |
|---------|----------------|
| Evento → Veículo | Opcional; depende do tipo (`veiculo = SIM`) para exibição do campo |
| Veículo → Evento | Não há relação `hasMany` no model `Veiculo`; eventos que usam o veículo são consultados via `Evento::where('idveiculo', ...)` se necessário |

---

## 4. Ligação com NF / Pedidos / Vendas

### 4.1 Campo `nf.idveiculo`

A nota fiscal (`nf`) pode referenciar um veículo. Isso é central nos **pedidos** (`Nf::scopePedido`: `tipo = C`, `saida = P`):

- **PedidoController**: lista e formulários carregam veículos; coluna “PLACA” na listagem; ao criar/editar pedido, o usuário associa o pedido de manutenção/abastecimento ao veículo.
- **Último KM na tela de pedido**: para cada veículo, busca-se a última NF de pedido que contenha itens com **`idprodserv` IN (20, 31)** — tratados no código como **diesel/combustível** — e expõe `ultimo_km` para apoio ao lançamento.

### 4.2 Vendas

- **VendaController** inclui lista de veículos em `create`/`edit` e duplicação de NF pode copiar `idveiculo`. Uso típico: receitas ligadas à frota quando aplicável.

### 4.3 Parcelas / outras telas NF

- **NfParcelaController**, **NfParcelaCreditoController**, **NfParcelaDebitoController**: ao editar parcela, carregam o veículo da NF pai (`nf.idveiculo`) para exibição contextual.

---

## 5. Contratos e `contratoveiculo`

- Tabela **`contratoveiculo`**: `idcontrato`, `idveiculo`, `idempresa`, auditoria.
- **ContratoController**: ao editar contrato, gerencia linhas de veículos do contrato (`addveiculo` / `removeveiculo` / update de `idveiculo` por linha).
- **VeiculoController::edit** lista **`ContratoVeiculo`** do veículo para visão inversa (em quais contratos o veículo aparece).

Isso alimenta **filtros** nos dashboards/Livewire: pedidos podem ser restritos a veículos que pertençam a um **`idcontrato`** via `whereExists` em `contratoveiculo`.

---

## 6. Dashboards e consumo (diesel / custo)

### 6.1 Convenções “mágicas” no código

Vários pontos assumem:

- **`idprodserv` 20 e 31** = itens de **combustível/diesel** (abastecimento).
- **`idprodservtipo` = 2** = classe de pedido de **manutenção/custo veículo** (não diesel) nos painéis de custo e listas.

Esses IDs são **configuração implícita** do projeto; em outro ambiente é preciso alinhar produtos/tipos reais.

### 6.2 `DashboardVeiculoController` (`/dashboard/veiculo`)

- Foco em **pedidos** com itens diesel (`whereIn('idprodserv', [20, 31])`).
- **`search`**: agrega pedidos filtrados, chama helpers globais `calcularMediaConsumo`, `calcularMediaConsumoPorMes`, monta média km/l por veículo (`calcularMediaConsumoPorVeiculo`) e lista de abastecimentos (`getListaAbastecimento`).
- **`getListaAbastecimento`**: join `nf` + `nfitem` + `veiculo` + `pessoa`; ordena priorizando `veiculo.dashboard`; para cada linha calcula **`ultimokm`** com **`getUltimoKmAntesDe($idVeiculo, $dataInicio)`** (ver abaixo).

### 6.3 `getUltimoKmAntesDe` (`app/Helpers/functions.php`)

Função global usada para relatórios de intervalo:

- Busca a NF do veículo com **dataentrada &lt; início do período**, join em `nfitem`, filtrando **`idprodserv` IN (20, 31)** — ou seja, **último registro de abastecimento/diesel antes do período**, não necessariamente qualquer NF.
- Retorna `nf.km` dessa linha ou **0**.

Isso permite estimar distância percorrida no período comparando com o hodômetro das NFs seguintes.

### 6.4 `DashboardVeiculoCustoController` (`/dashboard/veiculocusto`)

- Foco em pedidos **sem** diesel (`whereNotIn idprodserv`, `idprodservtipo = 2`).
- `getListaPedidos`: lista itens de manutenção com `ultimokm` análogo ao dashboard de diesel.
- Métodos auxiliares somam valores/quantidades de diesel em outros contextos (nomes de métodos misturam “diesel” com telas de custo — legado).

### 6.5 Livewire

| Componente | Função |
|------------|--------|
| **`PedidoVeiculoComponent`** | Pedidos no intervalo (`DateRangeService`), `idprodservtipo = 2`, exclui 20/31; filtros opcionais empresa, veículo, contrato; soma `valoritem`. |
| **`ListaPedidoVeiculoComponent`** | SQL raw com mesma lógica de pedidos/custo; aplica `getUltimoKmAntesDe` por veículo; escuta `filtersApplied`. |
| **`GraphMediaPedidoVeiculoComponent` / Js** | Gráficos de média de pedidos por veículo (integração com partials do dashboard). |
| **`VeiculoComponent`** | Apenas renderiza view (shell). |

### 6.6 `GraphMovimentacaoComponent` / `GraphMovimentacaoJsComponent`

- Queries de NF podem filtrar por **`idveiculo`** e/ou restringir a veículos de um **`idcontrato`** via subquery em `contratoveiculo`.

---

## 7. Fluxo de dados resumido

```mermaid
flowchart TB
  V[Veiculo cadastro]
  CV[ContratoVeiculo]
  EV[Evento idveiculo opcional]
  NF[Nf pedido/venda idveiculo km]
  V --> CV
  EV -.->|tipo veiculo SIM| V
  NF --> V
  NF -->|nfitem 20/31| DIESEL[Metricas diesel]
  NF -->|prodservtipo 2 sem 20/31| CUSTO[Metricas custo]
```

---

## 8. Boas práticas e riscos

1. **IDs de produto/tipo fixos (20, 31, tipo 2)** — documentar no ambiente ou externalizar para configuração.
2. **Status `Ativo` vs `ATIVO`** — alinhar scope `ativo()` com o que é gravado no admin.
3. **Corrigir `VeiculoController::fetch`** — colunas VENCIMENTO/STATUS.
4. **Duplicação** de lógica `getUltimoKmAntesDe` em `ListaPedidoVeiculoComponent` (método de instância) vs helper global — manter comportamento idêntico ao evoluir regras.
5. **Evento**: veículo é metadado do agendamento; faturamento continua dependente de venda/NF conforme módulo financeiro.

---

## 9. Referência de arquivos

| Arquivo | Papel |
|---------|--------|
| `VeiculoController.php` | CRUD admin, listagens, marcas/tipos/cores |
| `Veiculo.php` | Model, relações, scopes |
| `ContratoVeiculo.php` / `ContratoController` | Pivô e gestão no contrato |
| `DashboardVeiculoController.php` | Dashboard abastecimento/consumo |
| `DashboardVeiculoCustoController.php` | Dashboard custos de frota |
| `PedidoVeiculoComponent.php`, `ListaPedidoVeiculoComponent.php` | Livewire filtrável |
| `functions.php` | `getUltimoKmAntesDe`, `calcularMediaConsumo*`, `calcularMediaConsumoPorMes` |
| `PedidoController.php`, `VendaController.php` | NF + veículo + último KM |
| `admin/eventos/_form.blade.php` | Exibição condicional de `idveiculo` |
| `routes/web.php` | `veiculos`, `dashboard/veiculo`, `dashboard/veiculocusto` |

---

*Documento gerado a partir da leitura do código. Migrações podem acrescentar colunas não listadas aqui.*
