# Banners — Modelagem de Dados

## 1. Premissa: não existe tabela "banners"

O módulo é materializado por quatro tabelas já existentes:

| Tabela | Papel no módulo |
|---|---|
| `category_contents` | Classifica o conteúdo como `banners` (id 27) ou `super-banners` (id 33) |
| `contents` | O banner propriamente dito (título, `order`, `status`, `slug`, `carousel`, …) |
| `archives` | A imagem (`highlight = 1`) |
| `links` | A URL (`link`, `isBlank`, `alt`) |

## 2. `category_contents` — as duas categorias

Consulta real na base `prefeituras_v5`:

```sql
select id,name,slug,status,status_create,"order",category_contents_id,display_type
from category_contents where slug in ('banners','super-banners');

 id |     name      |     slug      | status | status_create | order | category_contents_id | display_type
----+---------------+---------------+--------+---------------+-------+----------------------+--------------
 27 | Banners       | banners       | t      | t             |       |                      |
 33 | Super Banners | super-banners | t      | t             |       |                      |
```

Ambas são categorias de **topo** (`category_contents_id IS NULL`), com `status_create = true`
(ou seja, **não** entram no "Mais Conteúdos" — ver `../mais-conteudos/`).

## 3. `contents` — colunas usadas

| Coluna | Tipo | Uso no módulo |
|---|---|---|
| `id` | `integer` PK | Identificador |
| `title` | `varchar(191)` | Título exibido no grid do CMS e no `alt` da imagem |
| `slug` | `varchar(191)` | Identificador do conteúdo |
| `order` | `integer` | **Banner comum**: ordem de exibição. **Super banner**: posição na tela (1 = topo/esquerda, 2 = base/direita) |
| `status` | `boolean` | Ativo/inativo |
| `category_contents_id` | `integer` NOT NULL (FK → `category_contents.id`) | 27 ou 33 |
| `deleted_at` | `timestamp` | Soft delete (as views SQL filtram `deleted_at IS NULL`) |
| `carousel`, `layout`, `referencia`, `linha_fina`, … | — | Herdados do conteúdo genérico, não usados por banners |

Conteúdos cadastrados (consulta real):

```sql
select count(*) from contents c
  join category_contents cc on cc.id = c.category_contents_id
  where cc.slug in ('banners','super-banners');   -- 6
```

| id | título | ordem | status |
|---|---|---|---|
| 172 | e-SIC | 1 | Ativado |
| 173 | Portal da Transparência | 2 | Ativado |
| 174 | Portal da Transparência - Governo Federal | 3 | Ativado |
| 175 | Licitações | 4 | Ativado |
| 176 | Super Banner 1 | 1 (topo) | Ativado |
| 177 | Super Banner 2 | 2 (base) | Ativado |

## 4. `archives` — a imagem

| Coluna | Valor no módulo |
|---|---|
| `contents_id` | FK para `contents.id` |
| `highlight` | `1` — marca o arquivo como **imagem principal** do banner |
| `path` | Caminho do arquivo, ex.: `storage/content/banners/<id>/destaque/<nome>` |
| `name`, `extension`, `type`, `title` | Metadados do arquivo |

No caso do `updateSuperBanner`, o `path` é reescrito para
`storage/content/super-banner/<nome>` (singular) — ver `05-REGRAS-E-PORTABILIDADE.md`.

## 5. `links` — a URL

| Coluna | Uso |
|---|---|
| `contents_id` | FK para `contents.id` |
| `link` | URL destino |
| `isBlank` | `1` = abrir em nova aba |
| `alt` | Texto alternativo da imagem (usado nos super banners do modelo5) |

Relacionamento: `Content::linksUnique()` é um `hasOne` para `Link` por `contents_id`
(`v6/app/Http/Model/Prefecture/Content.php:116`).

## 6. Views SQL

### 6.1 `banners`

Criada em `v6/database/migrations/2023_04_10_112025_create_view_to_banners.php` e
**substituída** por `v6/database/migrations/2023_04_18_132413_update_banners_view_to_order.php`
(a primeira ordenava por status/data; a segunda por `c.order`):

```sql
CREATE OR REPLACE VIEW public.banners
AS SELECT row_number() OVER (ORDER BY c.order asc) AS value,
    c.title AS titulo,
    CASE WHEN c.status IS TRUE THEN 'Ativado'::text ELSE 'Desativado'::text END AS status_name,
    c.id,
    c.status
FROM contents c
    JOIN category_contents cc ON cc.id = c.category_contents_id
WHERE c.deleted_at IS NULL AND cc.slug::text = 'banners'::text
ORDER BY c.order asc;
```

Colunas expostas: `value`, `titulo`, `status_name`, `id`, `status`.

### 6.2 `super_banners`

Criada em `v6/database/migrations/2023_04_10_132524_create_view_to_super_banners.php`
e reescrita por `v6/database/seeds/UpdateSuperBannersViewFixEmBaixo.php`:

```sql
CREATE OR REPLACE VIEW super_banners AS
SELECT
    row_number() OVER (ORDER BY (c.status IS TRUE) DESC, c.created_at DESC) AS value,
    c.title AS titulo,
    CASE WHEN c.status IS TRUE THEN 'Ativado'::text ELSE 'Desativado'::text END AS status_name,
    CASE
        WHEN c."order" = 1 THEN
            CASE WHEN (SELECT value FROM configurations conf WHERE conf.key = 'layout') = 'modelo5'
                THEN 'Esquerda'::text ELSE 'Em cima'::text END
        ELSE
            CASE WHEN (SELECT value FROM configurations conf WHERE conf.key = 'layout') = 'modelo5'
                THEN 'Direita'::text ELSE 'Em baixo'::text END
    END AS posicao,
    c.id AS id,
    c.status AS status
FROM contents c
JOIN category_contents cc ON cc.id = c.category_contents_id
WHERE c.deleted_at IS NULL AND cc.slug = 'super-banners'
ORDER BY (c.status IS TRUE) DESC, c.created_at DESC;
```

Colunas expostas: `value`, `titulo`, `status_name`, `posicao`, `id`, `status`.

Pontos críticos:

- A coluna `posicao` depende da **configuração de layout do portal**
  (`configurations.key = 'layout'`), lida por subconsulta dentro da view. Trocar o
  layout no CMS muda o rótulo exibido no grid **sem** precisar recriar a view.
- A ordenação é por `(status IS TRUE) DESC, created_at DESC` — **não** por `order`,
  ao contrário da view `banners`.
- A view é `CREATE OR REPLACE`, mas depende do `row_number()`; o replace falha se a
  ordem das colunas mudar.
- Existe ainda `v5/database/migrations/2025_09_30_215142_update_view_to_super_banners.php`
  que **não existe na v6** — divergência de versão (ver `08-GAPS-E-DIVIDAS.md`).

Estado real da view na base:

```sql
select value,titulo,status_name,posicao,id,status from super_banners;
 value |     titulo     | status_name | posicao  | id | status
-------+---------------+-------------+----------+----+--------
     1 | Super Banner 1 | Ativado     | Em cima  | 176 | t
     2 | Super Banner 2 | Ativado     | Em baixo | 177 | t
```

> `posicao = 'Em cima'/'Em baixo'` porque o layout ativo **não** é `modelo5`.

## 7. `configurations`

| Chave | Uso |
|---|---|
| `layout` | Valor `modelo5` (ou outro) consultado pela view `super_banners` |

A mesma informação é reproduzida no PHP por `objBanner($template)`
(`v6/app/Helpers/functions.php:921`):

```php
function objBanner($template)
{
    $data = null;

    if ($template == 'modelo5') {
        $data = [
            (object) collect(["id" => 1, "name" => 'Esquerda'])->all(),
            (object) collect(["id" => 2, "name" => 'Direita'])->all(),
        ];
    } else {
        $data = [
            (object) collect(["id" => 1, "name" => 'Em cima'])->all(),
            (object) collect(["id" => 2, "name" => 'Em baixo'])->all(),
        ];
    }

    return collect($data);
}
```

## 8. Registro do módulo

| Tabela | Registro |
|---|---|
| `modulos` | `id = 22`, `name = 'Banners'`, `slug = 'banners'`, `status = 1` |
| `menu_orders` | `id = 15`, `slug = 'banners'`, `modulo_id = 22` |
| `resources` | `id = 25` (`banners`) e `id = 26` (`super-banners`), ambos `modulo_id = 22` |

## 9. Migrations do módulo

| Migration | Efeito |
|---|---|
| `v6/database/migrations/2018_04_01_180916_create_category_contents_table.php` | Cria `category_contents` |
| `v6/database/migrations/2018_04_02_180433_create_contents_table.php` | Cria `contents` (inclui `order`, `status`, `carousel`) |
| `v6/database/migrations/2018_04_02_181807_create_archives_table.php` | Cria `archives` (inclui `highlight`) |
| `v6/database/migrations/2023_04_10_112025_create_view_to_banners.php` | Cria a view `banners` (ordem por status/data) |
| `v6/database/migrations/2023_04_18_132413_update_banners_view_to_order.php` | **Substitui** a view `banners` (ordem por `c.order`) |
| `v6/database/migrations/2023_04_10_132524_create_view_to_super_banners.php` | Cria a view `super_banners` |

## 10. Seeds

| Seed | Efeito |
|---|---|
| `v6/database/seeds/UpdateSuperBannersViewFixEmBaixo.php` | Reescreve a view `super_banners` com a mesma lógica (idempotência) |
| `v6/database/seeds/AddSuperBannerCarouselToLayoutSeeder.php` | Insere o bloco `super-banners-carousel` no modelo personalizável (tabela `layouts`), apontando para `portal.layouts.modelo5.home.super-banners` |
| `v6/database/seeds/AddToLayoutsNewTag.php` | Insere os blocos `super-banners-1` e `super-banners-2` no modelo 5 |

Layouts relacionados (consulta real na tabela `layouts`):

| key | section | type | path | status |
|---|---|---|---|---|
| `banners` | `home-news` | element | `portal.layouts.modelo5.home.news.sidebar` | t |
| `banners-2` | `home-news` | element | `portal.layouts.modelo5.home.news.sidebar` | f |
| `super-banners` | `content` | section | `portal.layouts.modelo5.home.super-banners` | t |
| `super-banners-1` | `super-banners` | element | `portal.layouts.modelo5.home.super-banners` | t |
| `super-banners-2` | `super-banners` | element | `portal.layouts.modelo5.home.super-banners` | t |
| `super-banners-carousel` | `super-banners-carousel-tags` | element | `portal.layouts.modelo5.home.super-banners` | t |
