# Estagiários — Gaps, Dívidas e Regressão v5 → v6

> Versão analisada: `v5`. O módulo **não existe** na `v6`; a seção
> "Regressão v5 -> v6" (seção 5) é obrigatória neste dossiê.

---

## 1. Bugs e erros conhecidos

| # | Severidade | Problema | Evidência | Impacto |
|---|---|---|---|---|
| B01 | Alta | Rotas de escrita (`store`, `update`, `destroy`) dispensam verificação de permissão: basta estar logado | `v5/app/Http/Middleware/CheckRoutePermission.php` (lista `resourceRoutes` = `update`/`store`/`destroy`) | Qualquer usuário autenticado (in Inclusive de perfil restrito) pode criar, alterar e excluir estagiários |
| B02 | Alta | Endpoint `datatable.estagiario` liberado a qualquer usuário logado (`datatable` está em `openRoutes`) | `v5/app/Http/Middleware/CheckRoutePermission.php` | Vazamento do JSON completo (inclui a coluna `arquivo` com os caminhos dos anexos) |
| B03 | Alta | SQL concatenado no filtro de busca do portal | `v5/app/Http/Controllers/Portal/EstagiariosController.php` (`whereRaw` + `clean_slug`) | SQL injection potencial se `clean_slug` mudar; sem binding hoje |
| B04 | Alta | Mensagem de exceção interna exibida ao operador (`flash($e->getMessage())->error()`) | `v5/app/Http/Controllers/Prefecture/EstagiarioController.php` (`store`/`update`) | Exposição de detalhes de SQL/caminhos de arquivo |
| B05 | Alta | Dados pessoais (nome completo, lotação, PDFs) publicados sem base legal nem aviso de privacidade | views do portal + exportações públicas | Exposição de dados pessoais (LGPD) |
| B06 | Média | Arquivo removido da lista **não** é apagado do disco | `EstagiarioController@destroyArquivo` | PDFs órfãos em `storage/app/public/docs` |
| B07 | Média | Datas inválidas são gravadas como `1970-01-01` | `prepareData()` (`strtotime` sem checagem) + Request sem `date_format` | Dados corrompidos sem aviso ao operador |
| B08 | Média | Coluna "ID" da listagem do CMS exibe o `row_number()` da view, não o `id` | `estagiarios_view` + `runDatatables` (`data: 'value'`) | Usuário confunde a numeração com o identificador do registro |
| B09 | Média | Arquivo `.csv` exportado contém HTML (o `FromView` do Maatwebsite) | `v5/app/Exports/EstagiariosExport.php` + `Portal\EstagiariosController@export` | Arquivo não abre corretamente em planilhas |
| B10 | Média | A listagem do CMS carrega a tabela inteira em memória | `DatatableController@get_estagiario` (`->get()` antes do `make(true)`) | Alto consumo de memória conforme o volume cresce |
| B11 | Média | A exportação ignora a paginação e carrega todo o resultado | `Portal\EstagiariosController@index` (`$query->get()`) | Timeout/OOM com muitos estagiários |
| B12 | Baixa | Slug recalculado a cada edição quebra URLs públicas | `Estagiario::boot()` (`updating`) | Links externos e indexados quebram |
| B13 | Baixa | Extração `.csv` sem cabeçalho (só no PDF) | `v5/resources/views/exports/estagiarios.blade.php` (`@if(isset($pdf))`) | Planilha sem título nem data da pesquisa |
| B14 | Baixa | Sem pasta `estagiarios` no template `default` | `v5/resources/views/portal/layouts/default/` | Se `configurations.layout` for `default`, a rota pública estoura erro de view inexistente |
| B15 | Baixa | `menu_orders.clicks` do slug `estagiario` nunca é incrementado (`menuClicks()` não é chamado) | `v5/app/Helpers/functions.php:822` | Com `menu_interativo = 1`, o item fica sempre no fim do menu |

## 2. Funcionalidades incompletas ou mortas

| Item | Situação |
|---|---|
| Auditoria (`activity()`) | Nunca chamada no módulo — nenhuma trilha de quem cadastrou/alterou/excluiu |
| Contador de acessos (`menuClicks`) | Implementado na plataforma, ausente no módulo |
| Filtros no CMS | Não existem; a listagem só tem a busca client-side do DataTable |
| Ordenação da listagem do CMS | O `value` (numeração) e o nome são ordenáveis, mas a ordenação padrão é pela coluna `value` (`row_number`), não pelo nome |
| Mensagem "Pelo menos um arquivo é obrigatório." | Inalcançável: a regra é `nullable|array` |
| Regra `situacao` | Aceita qualquer string no servidor (só o `<select> restringe) |
| Link no menu do portal | Não existe link estático nem registro em `contents`/`links` — a página só é acessível por URL direta |
| Permissões `estagiario.*` | Não existem linhas em `permissions`; apenas `super-admin` acessa o módulo |
| Frases de exportação no CMS | O DataTable do CMS exporta o que está na tela (client-side), com título dinâmico; a exportação oficial (servidor) só existe no portal |

## 3. Riscos de dados (migração de schema)

| Risco | Descrição | Mitigação |
|---|---|---|
| D01 | Tabela `estagiarios` não existe na v6; os dados cadastrados na v5 não têm destino na v6 | Exportar `estagiarios` (CSV/SQL) antes de qualquer migração; o dump da v5 é a única cópia |
| D02 | O campo `arquivo` (JSON) não tem integridade referencial | Converter para tabela `estagiario_arquivos` com backfill idempotente e conferência de contagem |
| D03 | `lotacao` é texto livre: não há como garantir que o título exista na lista de secretarias | Migrar para FK, criando uma linha "órfã" para os títulos não encontrados |
| D04 | O `slug` é único e gerado a partir de `nome-id` | Preservar os slugs existentes durante a migração para não quebrar links públicos |
| D05 | A view `estagiarios_view` é a fonte da listagem do CMS | Recriar a view na v7 ou eliminar a dependência (consulta direta com `whereNull('deleted_at')`) |
| D06 | Soft delete sem política de expurgo | Definir política de retenção e expurgo dos registros excluídos |
| D07 | PDFs em `storage/app/public/docs` são servidos publicamente | Migrar para disco privado, com rota autenticada e log de acesso |

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

1. O módulo deve voltar na v7? Se sim, com o mesmo formato público (lista + ficha
   + download de PDFs) ou com dados anonimizados?
2. Quem pode excluir estagiários e quem responde pelo espelho dos dados? A
   falta de trilha de auditoria é aceitável?
3. Os PDFs anexados (termo de estágio assinado) contêm dados pessoais sensíveis?
   Em caso afirmativo, o download deve exigir autenticação?
4. As lotações devem ser mantidas como texto ou viram referência à
   secretaria/órgão?
5. "Encerrado" e "Rescindido" são suficientes? Há outros desfechos previstos
   (renovação, suspensão)?
6. A listagem deve exibir estagiários inativos? Hoje a listagem mostra todos,
   sem filtro obrigatório por situação.
7. Existe volume alto de estagiários que justifique paginação server-side e
   fila de exportação?
8. Quem é o responsável por atualizar o portal quando o tema (layout) muda?
   O módulo depende de cópias em 6 templates.

## 5. Regressão v5 -> v6

A v6 **removeu o módulo Estagiários por completo**. Não há divergência de
comportamento: não existe nenhuma linha de código do módulo na v6.

### 5.1 Verificação de ausência

```bash
cd /home/one/projects/maxima/v7
grep -rni "estagiario" v6/ | wc -l      # 0
ls v6/app/Http/Controllers/Prefecture/ | grep -i estagiario   # nada
ls v6/app/Http/Controllers/Portal/ | grep -i estagiario        # nada
```

No banco da v6 (container `v6_6f22e1bd-postgres-1`, base `prefeituras_v5`):

```sql
SELECT count(*) FROM resources WHERE slug = 'estagiario';        -- 0
SELECT count(*) FROM menu_orders WHERE slug = 'estagiario';      -- 0
SELECT count(*) FROM pg_tables WHERE tablename = 'estagiarios';  -- 0
SELECT count(*) FROM pg_views WHERE viewname = 'estagiarios_view';-- 0
```

### 5.2 O que foi perdido

| Camada | Elemento na v5 | Situação na v6 | Arquivo de origem na v5 |
|---|---|---|---|
| Rotas do CMS | 7 rotas (`estagiario.index/create/edit/store/update/destroy/destroy-arquivo`) | **Removidas** | `v5/routes/basepro.php:329-336` |
| Rota de dados | `datatable.estagiario` | **Removida** | `v5/routes/basepro.php:421` |
| Rotas do portal | `estagiarios.index`, `estagiarios.show` | **Removidas** | `v5/routes/web.php:153-155` |
| Breadcrumb | `estagiarios`, `estagiarios.show` | **Removido** | `v5/routes/breadcrumbs.php:168-177` |
| Controller do CMS | `Prefecture\EstagiarioController` | **Removido** | `v5/app/Http/Controllers/Prefecture/EstagiarioController.php` |
| Controller do portal | `Portal\EstagiariosController` | **Removido** | `v5/app/Http/Controllers/Portal/EstagiariosController.php` |
| Model | `App\Http\Model\Prefecture\Estagiario` | **Removido** | `v5/app/Http/Model/Prefecture/Estagiario.php` |
| Form Request | `App\Http\Requests\EstagiarioRequest` | **Removido** | `v5/app/Http/Requests/EstagiarioRequest.php` |
| Export | `App\Exports\EstagiariosExport` | **Removido** | `v5/app/Exports/EstagiariosExport.php` |
| View de exportação | `exports/estagiarios.blade.php` | **Removida** | `v5/resources/views/exports/estagiarios.blade.php` |
| Views do CMS | `index`, `create`, `edit`, `form` | **Removidas** | `v5/resources/views/prefecture/estagiarios/` |
| Views do portal | `index`, `show`, `filtro` em 6 templates (18 arquivos) | **Removidas** | `v5/resources/views/portal/layouts/modelo1..modelo6/estagiarios/` |
| Componente do portal | `portal/components/estagiarios/table.blade.php` | **Removido** | `v5/resources/views/portal/components/estagiarios/table.blade.php` |
| JS do DataTable | `assets/js/custom/config/estagiarios/datatable.js` | **Removido** | `v5/public/assets/js/custom/config/estagiarios/datatable.js` |
| Migration da tabela | `create_estagiarios_table` | **Removida** | `v5/database/migrations/2026_05_26_200000_create_estagiarios_table.php` |
| Migration da view SQL | `create_view_estagiarios` | **Removida** | `v5/database/migrations/2026_05_26_200001_create_view_estagiarios.php` |
| Migration de menu/resource | `insert_estagiario_menu_and_resource` | **Removida** | `v5/database/migrations/2026_05_26_200002_insert_estagiario_menu_and_resource.php` |
| Item de menu do CMS | `menu_orders.slug = 'estagiario'` (id 35 na v5) | **Removido** (nenhum registro equivalente na v6) | migration `2026_05_26_200002` |
| Recurso de permissão | `resources.slug = 'estagiario'` (id 15, "Estagiários") | **Removido** (nenhum registro equivalente na v6) | migration `2026_05_26_200002` |
| Item de menu do AdminLTE | `case 'estagiario'` no `BuildingMenu` | **Removido** | `v5/app/Providers/MenuServiceProvider.php:370-372` |
| Tabela | `estagiarios` (11 colunas) | **Não existe** na v6 | — |
| View SQL | `estagiarios_view` | **Não existe** na v6 | — |

### 5.3 Impacto funcional da remoção

| Área | O que a prefeitura perdeu |
|---|---|
| Portal público | A página `/estagiarios` (listagem, ficha individual, filtros por nome/lotação/situação) e as quatro exportações (xls, pdf, csv, txt) |
| Transparência | A divulgação pública dos estagiários contratados, do período do contrato e da lotação |
| CMS | O cadastro, a edição, a exclusão lógica, o upload de PDFs e a listagem em DataTable |
| Permissões | O recurso `estagiario` (id 15) e o item de menu `estagiario` (id 35) — inclusive a **entrada** de menu, que nem aparece no AdminLTE da v6 |
| Dados | Todos os registros de `estagiarios` (a tabela está vazia no banco de desenvolvimento da v5, mas pode conter dados em produção) |
| Integrações | Nenhuma — o módulo não era consumido por outros módulos |

### 5.4 Observações específicas sobre a resource `estagiario` (id 15) e o menu

- A migration `v5/database/migrations/2026_05_26_200002_insert_estagiario_menu_and_resource.php`
  é a responsável por criar **os dois** registros: o item de menu
  (`menu_orders.slug = 'estagiario'`, `clicks = 0`) e o recurso
  (`resources.slug = 'estagiario'`, `name = 'Estagiários'`,
  `description = 'Funcionalidade Estagiários'`).
- Sem o item em `menu_orders`, o `MenuServiceProvider` nunca entra no
  `case 'estagiario'` e o item "Estagiários" não aparece no menu lateral do
  CMS; sem o registro em `resources`, o administrador de permissões não tem
  contra o que associar as ações `index/create/edit/delete`.
- A v6 possui a tabela `modulos` (58 módulos, por
  `v6/database/migrations/2024_11_01_150206_create_modulos_table.php`) e as
  colunas `resources.modulo_id` e `menu_orders.modulo_id` — mas **nenhum módulo
  "Estagiários"** e nenhuma resource/menu com o slug `estagiario`. A
  reconstrução na v7 exige criar também o registro em `modulos`.

## 6. Mapa v5 → v6 (resumo)

| Item | v5 | v6 | Ação na v7 |
|---|---|---|---|
| Tabela `estagiarios` | existe | não existe | recriar |
| View `estagiarios_view` | existe | não existe | recriar ou eliminar a dependência |
| Rotas CMS | 7 | 0 | recriar |
| Rota de DataTable | 1 | 0 | recriar (com paginação e permissão) |
| Rotas do portal | 2 | 0 | recriar |
| Controller CMS | 1 | 0 | recriar |
| Controller do portal | 1 | 0 | recriar |
| Model / Request / Export | 1 / 1 / 1 | 0 / 0 / 0 | recriar |
| Views (CMS + portal + componente) | 4 + 18 + 1 | 0 | recriar (template único) |
| JS do DataTable | 1 | 0 | recriar |
| Migrations | 3 | 0 | recriar (adaptadas) |
| `resources` (`estagiario`) | id 15 | ausente | recriar com `modulo_id` |
| `menu_orders` (`estagiario`) | id 35 | ausente | recriar com `modulo_id` |
| `modulos` ("Estagiários") | tabela inexistente | ausente (58 módulos) | criar |
| Permissões `estagiario.*` | inexistentes | inexistentes | criar |
| Dados dos estagiários | na base da v5 | perdidos | migrar do dump da v5 |
