# Manual do Sistema — Rotas e Controllers

> Todas as rotas no grupo `cms` de `v6/routes/basepro.php` (prefixo `/cms`).
> O grupo carrega o middleware `web`; a autorização vem do
> `check.route.permission`, registrado no construtor de cada controller.

---

## 1. Rotas dos manuais

| Método | URI | Nome | Controller@action | Middleware | Linha |
|---|---|---|---|---|---|
| GET | `/cms/manual-usuario` | `manual-usuario.index` | `Prefecture\ManualController@index` | `web` + `check.route.permission` | `v6/routes/basepro.php:211` |
| GET | `/cms/manual-usuario/create` | `manual-usuario.create` | `@create` | idem | 211 |
| POST | `/cms/manual-usuario` | `manual-usuario.store` | `@store` | idem | 211 |
| GET | `/cms/manual-usuario/{manual_usuario}` | `manual-usuario.show` | `@show` | idem | 211 |
| GET | `/cms/manual-usuario/{manual_usuario}/edit` | `manual-usuario.edit` | `@edit` | idem | 211 |
| PUT/PATCH | `/cms/manual-usuario/{manual_usuario}` | `manual-usuario.update` | `@update` | idem | 211 |
| DELETE | `/cms/manual-usuario/{manual_usuario}` | `manual-usuario.destroy` | **`@destroy` inexistente** | idem | 211 |
| GET | `/cms/manual/delete/{id}` | `manual.delete` | `@delete` | idem | `v6/routes/basepro.php:227` |

> A exclusão real é feita por `GET /cms/manual/delete/{id}` (operação
> destrutiva por GET, sem CSRF efetivo). A rota `manual-usuario.destroy`
> gerada pelo `Route::resource` aponta para um método que **não existe** —
> resultará em erro 500.
>
> O parâmetro do resource é `{manual_usuario}` (derivado do nome
> `manual-usuario`); o controller, porém, recebe apenas `$id` posicional
> — o Laravel passa o valor do parâmetro pela ordem, então funciona.

## 2. Rotas das áreas

| Método | URI | Nome | Controller@action | Middleware | Linha |
|---|---|---|---|---|---|
| GET | `/cms/manual-area` | `manual-area.index` | `Prefecture\ManualAreaController@index` | `web` + `check.route.permission` | `v6/routes/basepro.php:212` |
| GET | `/cms/manual-area/create` | `manual-area.create` | **`@create` inexistente** | idem | 212 |
| POST | `/cms/manual-area` | `manual-area.store` | `@store` | idem | 212 |
| GET | `/cms/manual-area/{manual_area}` | `manual-area.show` | **`@show` inexistente** | idem | 212 |
| GET | `/cms/manual-area/{manual_area}/edit` | `manual-area.edit` | `@edit` | idem | 212 |
| PUT/PATCH | `/cms/manual-area/{manual_area}` | `manual-area.update` | `@update` | idem | 212 |
| DELETE | `/cms/manual-area/{manual_area}` | `manual-area.destroy` | `@destroy` | idem | 212 |
| GET | `/cms/manual/get/{id}` | *(sem nome)* | `@getAll` | idem | `v6/routes/basepro.php:245` |

> O JS consome `/cms/manual/get/{id}` (rota **sem nome**) para listar as
> áreas de um manual.

## 3. Controllers

### 3.1 `Prefecture\ManualController`

`v6/app/Http/Controllers/Prefecture/ManualController.php` (140 linhas).

| Action | Comportamento | Linhas |
|---|---|---|
| `__construct(IManualUsuarioRepository $repository)` | injeta o repository, monta `$this->table = app(Manual::class)` e registra `check.route.permission` | 21-27 |
| `index()` | `$this->table->orderBy('created_at')->get(['id','titulo'])` -> view `manual-usuario.index` | 34-42 |
| `create()` | view `manual-usuario.create` (sem `$data`) | 47-50 |
| `store(ManualSistemaRequest $request)` | `$this->repository->upInsert($request)`; em sucesso redireciona para `manual-usuario.edit` | 58-72 |
| `show($id)` | `$this->table->where('id',$id)->with('areas')->first()` -> view `manual-usuario.show` | 81-88 |
| `edit($id)` | `$this->table->where('id',$id)->first()` -> view `manual-usuario.create` com `$data` | 95-102 |
| `update(Request $request, $id)` | `$this->repository->upInsert($request, $id)`; redireciona para `manual-usuario.show` | 110-123 |
| `delete($id)` | `$this->table->destroy($id)`; redireciona para `manual-usuario.index` | 126-139 |

Pontos críticos:

- **`update` usa `Request`, não `ManualSistemaRequest`** — a atualização
  **não valida** título/objetivo. Um `PUT` com campos vazios grava
  registros vazios (o banco rejeita `titulo`/`objetivo` NOT NULL, mas
  `url_portal`/`url_cms` podem ser gravados como string vazia ou `null`).
- `index()` ordena por `created_at` e a view reordena por título
  (`collect($content)->sortBy('titulo')`) — a ordenação do controller é
  inútil.
- `edit()` renderiza a **view de criação**, não uma view própria.
- Nenhuma chamada a `activity()`: o módulo **não é auditado**.
- `store` redireciona para `manual-usuario.edit` (o usuário cai
  imediatamente na tela de edição, já com as áreas).

### 3.2 `Prefecture\ManualAreaController`

`v6/app/Http/Controllers/Prefecture/ManualAreaController.php` (94 linhas).

| Action | Retorno | Linha |
|---|---|---|
| `index()` | **Collection Eloquent cru** (não é JSON nem view) — todas as áreas com `archive`, ordenadas por `id` | 25-28 |
| `store(Request $request)` | `response()->json(true)` ou `response()->json(false)` | 36-46 |
| `edit($id)` | **Model cru** da área com `archive` | 52-55 |
| `getAll($id)` | **Collection crua** das áreas do manual (`manual_id = $id`) | 57-60 |
| `update(Request $request, $id)` | `response()->json(true/false)` | 69-79 |
| `destroy($id)` | `response()->json(true/false)` | 85-93 |

Pontos críticos:

- `index()`, `edit()` e `getAll()` devolvem **Eloquent** diretamente. O
  Laravel 5.5 serializa models para JSON automaticamente, mas o formato
  expõe **todos** os atributos, inclusive `deleted_at` e `created_at`, e
  o `manual_id` — nada disso é filtrado.
- `store` e `update` **não validam** nada: um `POST` sem `titulo` chega ao
  repository e falha no banco (violação de NOT NULL) — e o
  `Repository::upInsert` faz `dd($th)`, **vazando a exceção** na tela.
- `destroy` apaga a área mas **não** apaga o arquivo em disco nem o
  registro em `archives` (órfãos).
- Nenhuma chamada a `activity()`.

---

## 4. Permissões exigidas

O módulo **não** faz checagem de permissão no corpo dos controllers. A
autorização vem exclusivamente do middleware `check.route.permission`,
que deriva a permissão do **nome da rota**:

| Rota | Permissão avaliada | Existe no catálogo `resources`? |
|---|---|---|
| `manual-usuario.index` | `manual-usuario.index` | **Não** |
| `manual-usuario.create` | `manual-usuario.create` | **Não** |
| `manual-usuario.store` | — | liberada pelo bug do middleware |
| `manual-usuario.show` | `manual-usuario.show` | **Não** |
| `manual-usuario.edit` | `manual-usuario.edit` | **Não** |
| `manual-usuario.update` | — | liberada pelo bug do middleware |
| `manual.delete` | `manual.delete` | **Não** |
| `manual-area.*` | `manual-area.*` | **Não** |
| `/cms/manual/get/{id}` | (rota sem nome) | o middleware cai no `hasAccessSegment()` |

Como **nenhuma** dessas chaves existe em `resources`, o resultado é:

- `super-admin` → acesso total (bypass em `has_access`/`CheckRoutePermission`);
- qualquer outro perfil → **bloqueado** em todas as rotas do módulo.

Ver `05-REGRAS-E-PORTABILIDADE.md` seção 3.1 para a falha do middleware
que libera `store`/`update`/`destroy`.

> A view `manual-usuario.index` usa
> `has_access(['manual-usuario.create'])` para exibir o botão
> "Cadastrar" — que, portanto, só aparece para `super-admin`.

---

## 5. Form Requests e validações

`v6/app/Http/Requests/ManualSistemaRequest.php`:

```php
public function rules()
{
    $rules = [
        'titulo'   => 'required',
        'objetivo' => 'required'
    ];
    return $rules;
}

public function messages()
{
    return [
        'titulo.required'   => 'O campo Título é obrigatório.',
        'objetivo.required' => 'O campo de Objetivo é obrigatório.'
    ];
}
```

| Action | Request | Valida? |
|---|---|---|
| `store` | `ManualSistemaRequest` | Sim (`titulo`, `objetivo`) |
| `update` | `Request` (genérico) | **Não** |
| `ManualAreaController@store` | `Request` (genérico) | **Não** |
| `ManualAreaController@update` | `Request` (genérico) | **Não** |

---

## 6. API Resources / Presenters

Nenhum. As respostas JSON são a serialização direta do Eloquent
(`Collection`/`Model`), sem Resource.

---

## 7. Rotas do portal público

Nenhuma. O módulo é **exclusivamente CMS**. Os campos `url_portal` e
`url_cms` são apenas links gravados para o operador — nada no portal lê a
tabela `manuals`.

O "Manual de Navegação" exibido no portal
(`v6/resources/views/portal/layouts/modelo1/informacoes-instituicao/acesso-rapido/manual-de-navegacao.blade.php`)
é uma **página estática** (`contents.text`), servida por
`route('static.show', 'manual-de-navegacao')` — **não** tem relação com
este módulo.
