# Novidades — Rotas e Controllers

> Todas as rotas no grupo `cms` de `v6/routes/basepro.php`, com
> middleware `check.logged`.

---

## 1. Rotas

| Método | URI | Nome | Controller@action | Middleware | Linha |
|---|---|---|---|---|---|
| GET | `/cms/novidades` | `changelog.index` | `Admin\ChangeLogController@index` | `web` + `check.logged` | `v6/routes/basepro.php:73` |
| GET | `/cms/novidades/editar/{id}` | `changelog.editar` | `@edit` | idem | 74 |
| GET | `/cms/novidades/create` | `changelog.create` | `@create` | idem | 75 |
| GET | `/cms/novidades/{id}` | `changelog.show` | **`@show` inexistente** | idem | 76 |
| POST | `/cms/novidades` | `changelog.store` | `@store` | idem | 77 |
| PUT | `/cms/novidades/update/{id}` | `changelog.update` | `@update` | idem | 78 |
| DELETE | `/cms/novidades/delete/{id}` | `changelog.delete` | `@destroy` | idem | 79 |

Observações:

- **Todas** as rotas têm `check.logged` — o módulo é interno, mas
  qualquer operador autenticado chega na tela.
- `changelog.show` aponta para um método que **não existe** no
  controller: `GET /cms/novidades/1` resulta em erro 500. A funcionalidade
  equivalente é o **modal** da listagem.
- Os verbos HTTP são mistos: `PUT` em `novidades/update/{id}` (o
  `Route::resource` usaria `PUT /cms/novidades/{id}`) e `DELETE` em
  `novidades/delete/{id}`. Não é REST, mas é consistente com o resto do
  CMS.
- Não há rota para a versão do sistema (`update_logs`): ela é apenas
  exibida no rodapé.

---

## 2. Controller

`v6/app/Http/Controllers/Admin/ChangeLogController.php` (105 linhas).

| Action | Comportamento | Linha |
|---|---|---|
| `index()` | `ChangeLog::orderBy('id','DESC')->get()` -> view `prefecture.configurations.changelog.index` | 15-19 |
| `create()` | view `prefecture.configurations.changelog.create` | 26-29 |
| `store(ChangeLogRequest $request)` | converte a data e grava campo a campo | 36-59 |
| `edit($id)` | `ChangeLog::findOrFail($id)` -> view `...changelog.edit` | 66-70 |
| `update(ChangeLogRequest $request, $id)` | converte a data e faz `update($data)` | 77-96 |
| `destroy($id)` | `ChangeLog::findOrFail($id)->delete()` -> `redirect()->back()` | 103-106 |
| `show($id)` | **não implementado** | — |

### 2.1 Conversão da data (store e update)

```php
$data = $request->all();
if (!empty($data['data_versao'])) {
    try {
        $data['data_versao'] = Carbon::createFromFormat('d/m/Y H:i:s', $data['data_versao'])->format('Y-m-d H:i:s');
    } catch (\Exception $e) {
        try {
            $data['data_versao'] = Carbon::createFromFormat('d/m/Y', $data['data_versao'])->format('Y-m-d');
        } catch (\Exception $e) {
        }
    }
}
```

- O formato enviado pelo formulário é `d/m/Y H:i:s` (o campo
  `data_versao` usa o `datetimepicker` com `format: 'd/m/Y H:i:s'`).
- O **segundo `catch` está vazio**: se a data não for `d/m/Y`, a
  `Carbon::createFromFormat` lança `InvalidFormatException` e a
  requisição **morre com erro 500** (a exceção escapa do catch vazio).
- No `update`, o `Carbon::createFromFormat('d/m/Y', ...)` produz
  `Y-m-d` (sem hora), enquanto a coluna é `timestamp` — o PostgreSQL
  completa com `00:00:00`.
- O `store` grava **campo a campo** (`$changelog->title = ...`), o que
  ignora o `$fillable`; o `update` usa `$changelog->update($data)`, que
  respeita o `$fillable` (portanto `data_versao` convertida **é**
  gravada, mas qualquer campo fora do `$fillable` seria ignorado).

---

## 3. Form Request

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

```php
public function authorize()
{
    return true;
}

public function rules()
{
    return [
        'title'         => 'required|max:120|min:3',
        'numero_versao' => 'required',
        'descricao'     => 'required|min:3',
        'data_versao'   => 'required',
        'icon'          => 'required'
    ];
}
```

Observações:

- `authorize()` retorna `true` — **não há** autorização no Form Request.
- Não há `messages()` customizado: as mensagens são as padrão do Laravel
  traduzidas pelo `laravellegends/pt-br-validator`.
- `numero_versao` só é `required` (sem `string`, sem `max:20`, sem
  validação de formato). A view aplica `pattern="^[0-9]+(\.[0-9]+)*$"` no
  cliente, mas isso **não** é validado no servidor.
- `data_versao` só é `required` (sem `date`), por isso a conversão do
  Carbon pode explodir.

---

## 4. Permissões exigidas

As permissões são checadas **apenas na view**, com `has_access()`:

| Elemento da UI | Permissão | Onde |
|---|---|---|
| Cabeçalho da caixa "Novidades" | `changelog.index` | `v6/resources/views/prefecture/configurations/changelog/index.blade.php:11` |
| Botão "Cadastrar Novidades" | (dentro do mesmo `@if`) | linha 16-19 |
| Botão "Editar" | `changelog.edit` | linha 60-68 |
| Botão "Excluir" | `changelog.delete` | linha 69-76 |
| Botão "Saber mais" | (sem permissão) | linha 55-58 |

O controller **não** checa permissão alguma. A única barreira é o
middleware `check.logged`.

> **Nenhuma** dessas permissões existe no catálogo `resources`: não há
> recurso `changelog` nem `novidades`. Logo, para qualquer perfil que
> não seja `super-admin`, `has_access(['changelog.index'])` é `false` e a
> **caixa inteira (com o botão de cadastro) não é renderizada** — mas a
> **timeline é renderizada** (está fora do `@if`), e o botão "Saber mais"
> aparece sempre.

---

## 5. API Resources / Presenters

Nenhum. A listagem é um array de models passado à view; o modal monta o
HTML no cliente a partir do `input hidden` com a descrição completa.

---

## 6. Rotas do portal público

Nenhuma. O changelog é **exclusivamente interno ao CMS**.

O portal público exibe apenas a **versão do sistema**
(`update_logs.version`), via `v6/app/Providers/FooterServiceProvider.php`,
sem link para o changelog.

---

## 7. Rotas relacionadas (outros módulos)

| Método | URI | Nome | Controller@action | Linha |
|---|---|---|---|---|
| GET | `/cms/modulos` | `modulos.index` | `Admin\ModulosController@index` | `v6/routes/basepro.php:40` |
| POST | `/cms/modulos` | `modulos.update` | `Admin\ModulosController@update` | `v6/routes/basepro.php:41` |
| GET | `/cms/datatable/...` | — | (sem rota para changelog) | — |

> O changelog **não** tem endpoint AJAX: a listagem é renderizada no
> servidor (sem paginação).
