# Estagiários — Arquitetura

> Versão analisada: `v5` (Laravel 5.5 / PHP 7.2). O módulo não existe na `v6`.

---

## 1. Visão geral

Estagiários é um módulo **sem camada de serviço/repositório**: o padrão do
legado é `Route` → `Controller` → `FormRequest` → `Model` (Eloquent direto) →
`View`. A mesma tabela `estagiarios` é lida por dois controladores distintos:

- `Prefecture\EstagiarioController` — escrita e administração (CMS `/cms`).
- `Portal\EstagiariosController` — leitura pública, filtros e exportações.

A leitura do CMS **não** consulta a tabela: usa a view `estagiarios_view`, via
`Prefecture\DatatableController@get_estagiario` (endpoint genérico de
DataTable). A leitura do portal consulta o model direto.

## 2. Classes envolvidas

| Classe | Caminho | Papel |
|---|---|---|
| `Prefecture\EstagiarioController` | `v5/app/Http/Controllers/Prefecture/EstagiarioController.php` | CRUD do CMS, upload/remoção de arquivos, redirecionamentos com `flash()` |
| `Portal\EstagiariosController` | `v5/app/Http/Controllers/Portal/EstagiariosController.php` | Listagem pública, filtros, paginação, exportações (XLSX/PDF/CSV/TXT) |
| `Prefecture\Estagiario` | `v5/app/Http/Model/Prefecture/Estagiario.php` | Model Eloquent, `SoftDeletes`, geração de `slug` |
| `App\Http\Requests\EstagiarioRequest` | `v5/app/Http/Requests/EstagiarioRequest.php` | Validação do formulário (CMS) |
| `App\Exports\EstagiariosExport` | `v5/app/Exports/EstagiariosExport.php` | Export `FromView` (Maatwebsite Excel) a partir de `exports.estagiarios` |
| `Prefecture\DatatableController` | `v5/app/Http/Controllers/Prefecture/DatatableController.php` | Endpoint JSON `datatable.estagiario` usado pela listagem do CMS |
| `Prefecture\Controller` | `v5/app/Http/Controllers/Prefecture/Controller.php` | Controller base do CMS; o construtor aplica `check.route.permission` |
| `Admin\Controller` | `v5/app/Http/Controllers/Admin/Controller.php` | Controller base do portal (`getTemplateActived()`); o controller do portal herda dele |
| `FileTrait` | `v5/app/Http/Traits/FileTrait.php` | `saveUpload()`, `getFileName()`, `deleteFile()` (gravação em `storage/app/public/docs`) |
| `AppTrait` | `v5/app/Http/Traits/AppTrait.php` | Trait agregada ao controller base do CMS |
| `MenuServiceProvider` | `v5/app/Providers/MenuServiceProvider.php` | Constrói o menu do AdminLTE; `case 'estagiario'` cria o item "Estagiários" |
| `MenuOrder` | `v5/app/Http/Model/Prefecture/MenuOrder.php` | Contador de cliques do menu (`clicks`) |

## 3. Middleware na cadeia

| Middleware | Onde é aplicado | Efeito |
|---|---|---|
| `web` (grupo) | `v5/app/Providers/RouteServiceProvider.php` (`mapWebRoutes`, `mapBaseproRoutes`) | Sessão, cookies, CSRF, `SubstituteBindings` |
| `check.site.manutention` | grupo que envolve `v5/routes/web.php:4` | Bloqueia o portal se `configurations.pagina_em_manutencao = 1` |
| `check.logged` | apenas nas rotas GET do CMS (`v5/routes/basepro.php:330-332`) | Redireciona para o dashboard se não houver sessão Sentinel |
| `check.route.permission` | construtor de `Prefecture\Controller` (`v5/app/Http/Controllers/Prefecture/Controller.php:22`) | Valida `Sentinel::hasAnyAccess()` contra o nome da rota; se não logado, redireciona para `login` |

> **Consequência:** as rotas `store`, `update`, `destroy` e `destroy-arquivo`
> não declaram `check.logged` na rota, mas herdam `check.route.permission` do
> controller — por isso continuam exigindo sessão. Ver
> `05-REGRAS-E-PORTABILIDADE.md` para a granularidade dessa checagem.

## 4. Fluxo de requisição

### 4.1 CMS — leitura (listagem)

```text
GET /cms/estagiarios
  -> grupo web (CSRF, sessão) + check.logged
  -> check.route.permission  (nome da rota: estagiario.index)
  -> Prefecture\EstagiarioController@index
  -> view prefecture.estagiarios.index
  -> JS assets/js/custom/config/estagiarios/datatable.js
  -> runDatatables('estagiario', collums)
  -> GET /cms/datatable/estagiario   (route name: datatable.estagiario)
  -> Prefecture\DatatableController@get_estagiario
  -> DB::table('estagiarios_view')->get()
  -> struct_views($data, 'estagiario')  (adiciona edit/delete/active/inactivate)
  -> JSON (Yajra DataTables)
```

### 4.2 CMS — escrita

```text
POST /cms/estagiarios                     -> estagiario.store
PUT  /cms/estagiarios/atualizar/{id}      -> estagiario.update
DELETE /cms/estagiarios/excluir/{id}      -> estagiario.destroy
DELETE /cms/estagiarios/{id}/arquivo/{index} -> estagiario.destroy-arquivo
  -> check.route.permission
  -> EstagiarioRequest (authorize() === true)
  -> prepareData(): normaliza datas dd/mm/aaaa -> Y-m-d
  -> FileTrait::saveUpload($file, 'docs', null, null, false)
  -> Estagiario::create($data) / ->update($data)
  -> flash('Estagiário cadastrado com sucesso.')->success()  (laracasts/flash + laralabs/toaster)
  -> redirect()->route('estagiario.index')
```

### 4.3 Portal — listagem e exportação

```text
GET /estagiarios?busca=&lotacao=&situacao=
  -> grupo web + check.site.manutention
  -> Portal\EstagiariosController@index
  -> Estagiario::query()->orderBy('nome')
       -> when(busca):   whereRaw(translate(lower(nome)) + ilike com clean_slug)
       -> when(lotacao): where('lotacao', $request->lotacao)
       -> when(situacao): where('situacao', $request->situacao)
  -> se $request->type: export($query->get(), $request->type)  (sem paginação)
  -> senão: $query->paginate(15)
  -> view portal.layouts.{layout}.estagiarios.index
       -> @include filtro + portal.components.estagiarios.table
```

### 4.4 Portal — ficha individual

```text
GET /estagiario/{slug}
  -> Portal\EstagiariosController@show
  -> Estagiario::where('slug', $slug)->firstOrFail()   (404 se não existir)
  -> view portal.layouts.{layout}.estagiarios.show
```

## 5. Diagrama (Mermaid)

```mermaid
graph TD
    A[GET /cms/estagiarios] --> B[check.logged]
    B --> C[check.route.permission]
    C --> D[Prefecture\EstagiarioController@index]
    D --> E[view prefecture.estagiarios.index]
    E --> F[datatable.js runDatatables]
    F --> G[GET /cms/datatable/estagiario]
    G --> H[DatatableController@get_estagiario]
    H --> I[(estagiarios_view)]

    J[POST/PUT/DELETE /cms/estagiarios (store, update, destroy)] --> K[check.route.permission]
    K --> L[EstagiarioRequest]
    L --> M[FileTrait::saveUpload]
    M --> N[(estagiarios)]
    N --> O[flash + redirect estagiario.index]

    P[GET /estagiarios] --> Q[Portal\EstagiariosController@index]
    Q --> R[(estagiarios)]
    Q --> S{type?}
    S -- sim --> T[EstagiariosExport / PDF / TXT]
    S -- nao --> U[paginate 15 + view portal]
    V[GET /estagiario/slug] --> W[Portal\EstagiariosController@show]
    W --> R
```

## 6. Dependências externas

Todas declaradas em `v5/composer.json`:

| Pacote | Versão | Uso no módulo |
|---|---|---|
| `laravel/framework` | `5.5.*` | base |
| `cartalyst/sentinel` | `2.0.*` | sessão e permissões (`has_access`, `check.route.permission`) |
| `maatwebsite/excel` | `^3.1` | `EstagiariosExport` (XLSX/CSV) |
| `barryvdh/laravel-dompdf` | `^0.8.7` | facade `PDF` para a exportação PDF |
| `yajra/laravel-datatables` | `^1.5` | JSON do DataTable do CMS |
| `laracasts/flash` | `3.0.*` | `flash()` nas mensagens de sucesso/erro |
| `laralabs/toaster` | `^2.0` | encadeamento `->success()` / `->error()` |
| `laravelcollective/html` | `^5.5` | `Form::open` / `Form::model` nos formulários |
| `diglactic/laravel-breadcrumbs` | `^4.0` | breadcrumb do portal (carrega `v5/routes/breadcrumbs.php`) |
| `jeroennoten/laravel-adminlte` | `1.22` | layout do CMS e menu lateral |

## 7. Observações de arquitetura

- **Sem API JSON:** o único JSON é o DataTable do CMS; não há `routes/api.php`
  para este módulo.
- **Sem cache/fila:** tudo é síncrono e sem cache.
- **Sem repository:** o model é usado diretamente nos dois controllers, o que
  duplica a definição de "situação" e "lotação" em views, controller e export.
- **Sem repositório/serviço de upload:** a manipulação do JSON de arquivos está
  concentrada no controller do CMS e replicada na view `form.blade.php` (leitura)
  e na view de exportação.
