# Avisos — Resumo Executivo

> **Versão analisada:** `v6` (módulo equivalente em `v5`)
> **Slug do módulo:** `avisos` (tabela `modulos`, id 26) — **categoria de conteúdo**
> `category_contents.slug = 'anuncios'` (id 28, "Anúncios")
> **Natureza:** CMS (painel administrativo) + Portal (público, via modal na home)
> **Estado:** OK v6 — com divergência de nomenclatura entre módulo e categoria

---

## 1. Objetivo

O módulo serve para a prefeitura publicar um **aviso** (comunicado institucional)
na home do portal: uma imagem (banner) com um link de destino, exibida em um *popup*
(modal) assim que o cidadão abre a página inicial. O operador cadastra o aviso no CMS
com título, link, imagem de destaque e a opção de "abrir em nova guia"; o portal
exibe **apenas um aviso por vez** — ativar um novo desativa o anterior.

## 2. Efeito / Impacto

| Faixa | Efeito |
|---|---|
| Cidadão | Ao entrar no portal, um modal abre com o comunicado e um link (imagem clicável). Não existe página pública de listagem de avisos. |
| Prefeitura (CMS) | Menu "Avisos" (`/cms/conteudos/anuncios`) com DataTable (título + status), cadastro com upload de imagem, alternância de status por linha. |
| Transparência e legalidade | Comunicados oficiais têm data de publicação e responsável (log de atividade) e ficam registrados em `contents` + `links`. |
| Operação técnica | O nome do módulo no CMS é `avisos`, mas a categoria de conteúdo é `anuncios` — duas identidades para a mesma feature. |

## 3. Comportamento

- O portal busca **um único** aviso ativo na home:

```php
// v6/app/Http/Controllers/Portal/PortalController.php:155-159
$anuncio = $this->content->with('categoryContents', 'archives', 'linksUnique')
    ->whereHas('categoryContents', function ($query) {
        $query->where('slug', '=', 'anuncios');
    })->where('status', 1)
    ->first();
```

- Ao cadastrar ou ativar um aviso com `status = 1`, o CMS **desativa todos os outros**
  avisos da categoria (`ContentController.php:672-674`, `:994-996`, `:1565-1567`).
- O link do aviso vive na tabela `links` (`Content.linksUnique()`), junto com `isBlank`
  ("abrir em nova guia").
- A imagem de destaque vive em `archives` com `highlight = 1`, no caminho
  `storage/content/anuncios/{id}/destaque/{nome}`, e é recomprimida para **700x405**.
- A listagem do CMS usa a view SQL `anuncios` (`value`, `titulo`, `status_name`, `id`, `status`).
- A listagem do portal **não existe**: o aviso só aparece como modal na home.

## 4. Como o Usuário Interage

**Operador (CMS)**

| Tela | Rota | Ação |
|---|---|---|
| Lista | `/cms/conteudos/anuncios` | DataTable `#tabela_anuncios`: ID, Título, Status, Ações; botão "Cadastrar Aviso"; exclusão em lote |
| Cadastro | `/cms/conteudos/cadastrar/anuncios` | Status (Ativar/Desativar), Título, Link, Imagem (upload com preview e editor), "Abrir em nova guia" |
| Edição | `/cms/conteudos/editar/anuncios/{id}` | Idem, com a imagem atual exibida |
| Status | `POST /cms/set-status` | Botão de toggle por linha (ícone liga/desliga) |

**Cidadão (portal)**

- Home do portal: o modal `#anuncio` é aberto automaticamente por script
  (`$('#btn-anuncio').click()`), com a imagem do aviso e o link de destino.
- Não há URL pública de avisos: o conteúdo só aparece na home.

## 5. Detalhes e Particularidades Técnicas

- Camadas (portal): `Route (web.php)` -> `Portal\PortalController@index` -> `Content` ->
  `contents` + `archives` + `links`; a view do layout desenha o modal.
- Camadas (CMS): `Route (basepro.php)` -> `ContentController` -> `ContentRequest` ->
  `Content`/`Archive`/`Link`; listagem por `DatatableController@get_avisos` -> view SQL `anuncios`.
- Dependências: `yajra/laravel-datatables-oracle`, `intervention/image` (compressão),
  jQuery + Bootstrap (modal), `cartalyst/sentinel` (permissões `anuncios.*`).

## 6. Estrutura de Dados

| Objeto | Detalhe |
|---|---|
| `contents` | `title` (título do aviso), `status` (ativo/inativo), `category_contents_id = 28` |
| `links` | `contents_id`, `link`, `isBlank` — destino do aviso |
| `archives` | `contents_id`, `highlight = 1`, `path` — imagem do aviso |
| view `anuncios` | `value`, `titulo`, `status_name` ('Ativado'/'Desativado'), `id`, `status` |
| `modulos` | id 26, `name = 'Avisos'`, `slug = 'avisos'`, `status = 1` |
| `resources` | `slug = 'anuncios'`, `name = 'Avisos'`, `modulo_id = 26` |

## 7. Como Testar

- CMS: cadastrar aviso com imagem, ativar, confirmar que os demais foram desativados,
  alternar status pela lista, editar o link, excluir.
- Portal: abrir a home e confirmar que o modal aparece com a imagem e o link corretos;
  confirmar que o aviso só abre para o usuário que está na home.
- Verificar que o `path` da imagem existe em `storage/app/public/content/anuncios/{id}/destaque/`.

## 8. Migração para Laravel Moderno

Criar `Announcement` (ou `Aviso`) com `title`, `image_path`, `url`, `open_in_new_tab`,
`active`, `starts_at`/`ends_at` (opcional), `FormRequest`, `AnnouncementPolicy`,
`GET /api/v1/avisos`, `POST /api/v1/avisos/{id}/ativar` (que garante exclusividade),
componente `<x-announcement.modal>` e uma regra de banco (`unique` parcial) para garantir
um único aviso ativo.

## 9. Resumo Geral

"Avisos" é o nome do módulo no registro do CMS (`modulos.slug = 'avisos'`, id 26) e
"Anúncios" é o nome da categoria de conteúdo (`category_contents.slug = 'anuncios'`,
id 28) — o mesmo recurso com dois nomes. O aviso é um `contents` com título, status e
imagem de destaque (`archives.highlight = 1`), mais um registro em `links` com a URL de
destino. O portal não tem rota nem página de avisos: o `PortalController@index` busca o
único aviso com `status = 1` e o exibe em modal na home, abrindo-o automaticamente por
script. O CMS garante a exclusividade: ativar um aviso desativa os demais da categoria.

---

## Í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 |
