# e-Vacina — Resumo Executivo

> **Versão analisada:** `v6` (idêntico à v5 neste módulo)
> **Slug do módulo:** `e-vacina` (tabela `modulos`, id 5, `status = false` — **desativado** por padrão)
> **Natureza:** CMS (painel administrativo)
> **Estado:** migrado v5 -> v6 (sem diferenças de código)

---

## 1. Objetivo

Manter os **dados de vacinação** exibidos no portal do município: a
população total, a URL de uma planilha do Google Sheets com os
registros de vacinação e os contadores de doses (1ª dose, 2ª dose,
1º reforço, 2º reforço), calculados a partir da planilha.

O módulo foi criado durante a pandemia de COVID-19 e é **um contador**:
o operador informa a população e o link da planilha; o sistema importa o
CSV, conta as doses e publica o resultado.

## 2. Efeito / Impacto

| Faixa | Efeito |
|---|---|
| Cidadão | Nenhum efeito direto (o portal não exibe esses dados na v6 — o consumidor do portal não foi identificado no código do CMS). |
| Prefeitura (CMS) | Permite ao gestor manter o painel de vacinação atualizado a partir de uma fonte externa. |
| Transparência e legalidade | irrelevante na v6. |
| Operação técnica | Depende de uma planilha do Google Sheets **pública** e de um comando artisan agendado mensalmente. |

## 3. Comportamento

- A tela é **única**: `GET /cms/e-vacina` carrega o **registro mais
  recente** (`Evacina::latest()->first()`) e renderiza o formulário de
  edição — não há listagem nem botão "novo".
- O formulário tem: caixa "Ativar/Desativar", imagem (banner),
  **População** e **URL** (a planilha do Google).
- O `status` é derivado da **presença** da checkbox `status_evacina`
  (`isset($request->status_evacina)`).
- Ao salvar, o controller chama `Artisan::call('reload:evacina')`, que:
  1. lê a URL da planilha (`spreadsheets/d/<id>/...gid=<n>`);
  2. exporta o CSV (`https://docs.google.com/spreadsheets/d/<id>/export?format=csv&gid=<n>`);
  3. grava o CSV em `storage/app/public/evacina/evacina.csv`;
  4. conta os valores da **coluna 28** (índice 28): `Dose`, `1ª Dose`,
     `2ª Dose`, `Dose Adicional`, `Reforço`, `2ª Reforço`;
  5. atualiza os 4 contadores **apenas se `status` for verdadeiro**.
- O comando `reload:evacina` é executado **mensalmente** pelo scheduler
  (`v6/app/Console/Kernel.php:26-28`).
- Erros no comando são **silenciosamente ignorados**
  (`catch (\Throwable $th) { // Ignorando Erro }`).

## 4. Como o Usuário Interage

- Menu de engrenagem do AdminLTE -> item **"e-Vacina"**
  (`v6/resources/views/vendor/adminlte/page.blade.php:263-270`), com guarda
  `has_access(['e-vacina.index']) && $modulos['e-vacina']` — como o
  módulo está **desativado** por padrão, o item **não aparece** até que
  o módulo seja ligado em `/cms/modulos`.
- A tela mostra o banner, a população e a URL, com um botão "Salvar".
- Um botão secundário "Criar Banner Personalizado" abre o modal de
  criação de banner do portal (reaproveitado do módulo de conteúdos).

## 5. Detalhes e Particularidades Técnicas

- Camadas: `Route` -> `Prefecture\EvacinaController` ->
  `EvacinaRequest` -> `IEvacinaRepository`/`EvacinaRepository` ->
  `App\Http\Model\Prefecture\Evacina` -> `evacinas`.
- O `EvacinaController::__construct()` **não** chama
  `parent::__construct()` -> o middleware `check.route.permission` da
  classe base `Prefecture\Controller` **não** é registrado; e a rota
  `Route::resource('e-vacina', ...)` **não** declara `check.logged`.
  O módulo é, portanto, **público**.
- `Route::resource` gera 7 rotas; o controller implementa **apenas**
  `index`, `store` e `update` — `create`, `show`, `edit` e `destroy`
  resultam em erro 500.
- O `update` **ignora o id da URL** e atualiza sempre o registro mais
  recente.
- O formulário posta para `url('cms/e-vacina/1')` — **id fixo 1**.
- Dependências: Google Sheets (fonte externa), `Storage`, `Artisan`.

## 6. Estrutura de Dados

| Tabela | Papel |
|---|---|
| `evacinas` | Uma linha por configuração (na prática, sempre a mais recente é usada) |
| `resources` | Recurso `e-vacina` (id 46) -> `modulo_id = 5` — **existe** (ao contrário de outros módulos) |
| `modulos` | Registro de módulos (id 5 = `e-vacina`, `status = false`) |

Views SQL: nenhuma.

Seeds: nenhum para `evacinas`. A migration
`v6/database/migrations/2022_09_06_091951_create_evacinas_table.php`
cria a tabela vazia.

## 7. Como Testar

- `GET /cms/e-vacina` sem sessão deve retornar 200 (comportamento
  atual — rota pública).
- Salvar com uma URL de planilha válida deve disparar
  `reload:evacina` e atualizar os contadores.
- Salvar com `status` desmarcado deve gravar `status = null` (e não
  `false`) por causa do `filter_request`.
- `GET /cms/e-vacina/create` deve retornar erro (método inexistente).

## 8. Migração para Laravel Moderno

- Model `Evacina` com `casts` (`status => boolean`,
  `populacao => float`), `SoftDeletes` e o import `SoftDeletes`
  corrigido.
- `StoreEvacinaRequest` / `UpdateEvacinaRequest` com `url` (url),
  `populacao` (numeric, min:1) e `image` (image).
- `EvacinaPolicy` + `auth` em todas as rotas.
- `EvacinaService` para a importação da planilha (separar do
  controller), com **fila** e reuso do resultado.
- Endpoints `GET/PUT /api/e-vacina` e `POST /api/e-vacina/refresh`.
- Job `RefreshEvacinaData` disparado após salvar e pelo scheduler.

## 9. Resumo Geral

"e-Vacina" é um contador de vacinação da pandemia: o operador informa a
população do município e a URL de uma planilha do Google Sheets, e o
comando `reload:evacina` (agendado mensalmente) baixa o CSV, conta as
doses nas colunas "1ª Dose", "2ª Dose", "Dose Adicional", "Reforço" e
"2º Reforço" e grava os quatro contadores. A tela é única
(`/cms/e-vacina` mostra o registro mais recente em modo de edição) e o
módulo é **desativado por padrão** em `modulos.status`. Os problemas:
as rotas do `Route::resource` não têm `check.logged` e o controller não
registra o middleware da classe base, tornando o módulo **público**;
quatro das sete rotas geradas apontam para métodos inexistentes; o
`update` ignora o id da URL e o formulário posta para um id fixo; o
`filter_request` converte `status = false` em `null`; e o comando de
importação engole **todas** as exceções sem registrar nada.

---

## Índice do dossiê

| Arquivo | Conteúdo |
|---|---|
| `00-RESUMO.md` | Este documento |
| `01-ARQUITETURA.md` | Camadas, classes e o diagrama de fluxo |
| `02-MODELAGEM.md` | Estrutura de dados detalhada |
| `03-ROTAS-E-CONTROLADORES.md` | Rotas, controllers, requests, resources |
| `04-VIEWS-E-UX.md` | Telas, componentes, JS, assets |
| `05-REGRAS-E-PORTABILIDADE.md` | Particularidades e armadilhas |
| `06-MIGRACAO-MODERNA.md` | Plano de reconstrução em Laravel moderno |
| `07-TESTES.md` | Estratégia e casos de teste |
| `08-GAPS-E-DIVIDAS.md` | Pendências, riscos, comparativo v5 vs v6 |
