# e-Vacina — Gaps, Dívidas e Divergências v5 → v6

> Módulo **sem qualquer consumidor no portal** e **desativado por
> padrão**. O código é idêntico entre v5 e v6.

---

## 1. Decisão pendente (bloqueante para a v7)

O módulo e-Vacina existe apenas para pandemic. Na v6:

- o módulo está **desativado** (`modulos.status = false`);
- **nenhum** rota, view ou serviço do portal público consome a tabela
  `evacinas`;
- o comando de importação falha **em silêncio**;
- a tela é pública.

Três caminhos possíveis:

| Opção | Descrição | Consequência |
|---|---|---|
| **A** | **Descontinuar**: remover o módulo do registro, a tabela e o comando | simplifica; o dado histórico é perdido |
| **B** | **Reformular** como um painel genérico de "indicadores de saúde" com fonte configurável | amplia o escopo; exige um consumidor no portal |
| **C** | **Manter** como está, apenas corrigindo segurança e robustez | menor esforço; mantém um módulo sem uso |

A recomendação é **A** ou **C**, conforme o contrato com o cliente. Em
qualquer caso, a **segurança** (rotas públicas) deve ser corrigida já
na v6, se ainda houver uso.

---

## 2. Bugs e erros conhecidos

| Sev. | Item | Arquivo / linha |
|---|---|---|
| **CRÍTICO** | As rotas do `Route::resource('e-vacina', ...)` **não têm `check.logged`** e o controller não registra `check.route.permission` -> o módulo é **público** (leitura e gravação) | `v6/routes/basepro.php:201` + `v6/app/Http/Controllers/Prefecture/EvacinaController.php:25-28` |
| **CRÍTICO** | O botão "Registrar" está **fora** do `<form>` -> o clique **não submete** o formulário | `v6/resources/views/prefecture/configurations/evacina/edit.blade.php` + `form.blade.php` |
| **ALTO** | `update` quebra com **erro fatal** quando não há nenhum registro (`$last_evacina->id` sobre `null`) | `v6/app/Http/Controllers/Prefecture/EvacinaController.php:58-64` |
| **ALTO** | O comando engole **todas** as exceções (`catch (\Throwable) { // Ignorando Erro }`) | `v6/app/Console/Commands/ReloadEvacina.php` |
| **ALTO** | 4 das 7 rotas geradas apontam para métodos inexistentes (`create`, `show`, `edit`, `destroy`) -> 500 | `v6/routes/basepro.php:201` |
| **MÉDIO** | `file_get_contents` sem timeout e sem User-Agent -> travamento da requisição | `v6/app/Console/Commands/ReloadEvacina.php` |
| **MÉDIO** | A coluna do CSV é fixa (índice 28) sem validação -> contadores silenciosamente errados se a planilha mudar | mesmo arquivo |
| **MÉDIO** | O CSV é lido de `storage_path('app/public/...')`, assumindo o symlink do disk `public` | mesmo arquivo |
| **MÉDIO** | `status = false` é gravado como **`null`** (por `filter_request`) | `v6/app/Http/Traits/AppTrait.php:523-534` |
| **MÉDIO** | `Repository::upInsert` faz `dd($th)` -> vazamento da exceção | `v6/app/Repositories/Repository.php:64-71` |
| **MÉDIO** | `populacao = 0` vira `null` numa coluna NOT NULL -> erro 500 | `v6/app/Http/Controllers/Prefecture/EvacinaController.php:45-52` |
| **MÉDIO** | Nenhuma auditoria (`activity()`) | `v6/app/Http/Controllers/Prefecture/EvacinaController.php` |
| **MÉDIO** | Sem flash de confirmação para o operador | mesmo controller |
| **MÉDIO** | A URL de origem é validada só como `required` (nem como URL) | `v6/app/Http/Requests/EvacinaRequest.php` |
| **BAIXO** | `use illuminate\Database\Eloquent\SoftDeletes;` (minúsculo) | `v6/app/Http/Model/Prefecture/Evacina.php` |
| **BAIXO** | Sem `casts` (`status` não é booleano no model) | mesmo arquivo |
| **BAIXO** | `<input type="hidden" name="title" value="e-Vacina">` (vestígio) | `v6/resources/views/prefecture/configurations/evacina/form.blade.php` |
| **BAIXO** | `</form>` fora de lugar (depois do `box-footer`) | `v6/resources/views/prefecture/configurations/evacina/edit.blade.php` |
| **BAIXO** | A tabela cresce a cada gravação (o `store` sempre insere) | `v6/app/Http/Controllers/Prefecture/EvacinaController.php:45-52` |
| **BAIXO** | Sem índice em `evacinas` (consulta `latest()->first()` faz full scan) | schema |
| **BAIXO** | A URL do Google (com o id da planilha) fica exposta na rota pública | `v6/routes/basepro.php:201` |
| **BAIXO** | `imagem_evacina` sem validação de tipo/tamanho | `v6/app/Http/Requests/EvacinaRequest.php` |

---

## 3. Funcionalidades incompletas ou mortas

| Item | Situação |
|---|---|
| Consumidor no portal público | **Inexistente** — a tabela `evacinas` não é lida por nenhuma view do portal |
| 4 rotas do `Route::resource` | Quebradas (métodos inexistentes) |
| Botão de submit da tela | Não funciona |
| Histórico de contagens | As linhas antigas existem, mas **não são lidas** por ninguém |
| Auditoria | Inexistente |
| Tratamento de falha da importação | Inexistente |
| Documentação da origem dos dados | Inexistente (o número da coluna 28 não é explicável por quem não leu o código) |

---

## 4. Mapa v5 → v6

| Aspecto | v5 | v6 |
|---|---|---|
| `Prefecture\EvacinaController` | idêntico | **idêntico** |
| `App\Http\Model\Prefecture\Evacina` | idêntico | **idêntico** |
| `EvacinaRequest` | idêntico | **idêntico** |
| `EvacinaRepository` | idêntico | **idêntico** |
| `ReloadEvacina` (comando) | idêntico | **idêntico** |
| Views `evacina/{edit,form}.blade.php` | idênticas | **idênticas** |
| Migration `create_evacinas_table` | idêntica | **idêntica** |
| Tabela `evacinas` | idêntica | **idêntica** |
| Registro de módulos | **inexistente** | `modulos` (id 5, `status = **false**`) |
| Recurso em `resources` | **inexistente** | `e-vacina` (id 46) -> `modulo_id = 5` |
| Preset `padrao` do formulário de módulos | inexistente | inclui `e-vacina` |

**Conclusão:** o código do módulo é **byte-a-byte idêntico** entre v5 e
v6. A v6 apenas o **registrou** no novo mecanismo de módulos (e o deixou
desativado por padrão) e criou o recurso de permissão.

> Diferença de **comportamento** entre v5 e v6: na v5 o item de menu
> (se existisse) apareceria; na v6 ele depende de
> `$modulos['e-vacina']`, que é `false` — logo o item **não aparece**
> até que o módulo seja ligado.

---

## 5. Riscos de dados

| Risco | Detalhe | Mitigação |
|---|---|---|
| `status` com valores `true`/`null` | estado ambíguo | `NOT NULL DEFAULT false` + cast |
| Sem índice | full scan a cada leitura | índice em `created_at` |
| Uma linha por gravação | crescimento sem limite | upsert (config singleton) |
| `path_imagem` relativo ao disk | quebra se o symlink mudar | `Storage::url()` |
| Contadores dependentes de coluna fixa | silenciosamente errados | parametrizar + logar o cabeçalho |
| Dependência externa única | planilha fora do ar -> módulo congelado | log + aviso na UI + alerta ao operador |
| Dados de saúde (população, doses) | não há dado pessoal, mas é dado público sensível | revisar a publicação |
| Tabela sem consumidor | dado escrito e nunca lido | decidir o futuro (opção A/B/C) |

---

## 6. Perguntas em aberto para o negócio

1. **O e-Vacina ainda é usado em alguma instalação?** A base analisada
   não tem dados na tabela e o módulo nasce desativado.
2. **Se não for mais usado, a tabela deve ser removida ou arquivada?**
3. **A planilha do Google é a fonte oficial?** Se a prefeitura usa um
   sistema próprio de vacinação, a importação precisa ser reescrita
   (API em vez de CSV).
4. **Quem mantém a planilha e a coluna 28?** Não há documentação.
5. **Os dados devem ser publicados no portal?** Não há consumidor hoje.
6. **É preciso manter o histórico de contagens?** Hoje as linhas
   antigas existem mas não são lidas.
7. **A URL da planilha pode ser sensible?** A rota é pública na v6.

---

## 7. Checklist de correção (priorizado)

| Prioridade | Item | Arquivo |
|---|---|---|
| P0 | Exigir autenticação em todas as rotas (`check.logged` + `check.route.permission` ou Policy) | `v6/routes/basepro.php:201` + `v6/app/Http/Controllers/Prefecture/EvacinaController.php:25-28` |
| P0 | Corrigir o botão de submit (dentro do `<form>` ou com `form="id"`) | `v6/resources/views/prefecture/configurations/evacina/edit.blade.php` |
| P0 | Corrigir o `update` para não quebrar sem registro | `v6/app/Http/Controllers/Prefecture/EvacinaController.php:58-64` |
| P1 | Registrar as falhas do comando (substituir o `catch` vazio) | `v6/app/Console/Commands/ReloadEvacina.php` |
| P1 | Adicionar timeout e User-Agent no download do CSV | mesmo arquivo |
| P1 | Substituir o `Route::resource` por rotas explícitas (só as implementadas) | `v6/routes/basepro.php:201` |
| P1 | Corrigir `Repository::upInsert` (não usar `dd($th)`) | `v6/app/Repositories/Repository.php:64-71` |
| P2 | `status` NOT NULL DEFAULT false + cast boolean | nova migration + `v6/app/Http/Model/Prefecture/Evacina.php` |
| P2 | Validar `url` como URL e `populacao` como numérica (min:1) | `v6/app/Http/Requests/EvacinaRequest.php` |
| P2 | Validar `imagem_evacina` (image, tamanho) | mesmo arquivo |
| P2 | Parametrizar a coluna do CSV e logar o cabeçalho detectado | `v6/app/Console/Commands/ReloadEvacina.php` |
| P2 | Corrigir o import `illuminate` minúsculo | `v6/app/Http/Model/Prefecture/Evacina.php` |
| P2 | Emitir flash de sucesso/erro | `v6/app/Http/Controllers/Prefecture/EvacinaController.php` |
| P2 | Índice em `created_at` | nova migration |
| P3 | Remover o `input hidden` `title` | `v6/resources/views/prefecture/configurations/evacina/form.blade.php` |
| P3 | Corrigir a posição do `</form>` | `v6/resources/views/prefecture/configurations/evacina/edit.blade.php` |
| P3 | Registrar auditoria (`activity()`) | `v6/app/Http/Controllers/Prefecture/EvacinaController.php` |
| P3 | Consolidar em uma única linha (upsert) em vez de inserir a cada gravação | mesmo controller |
