# Destaques — Gaps, Dívidas e Mapa v5 → v6

## 1. Bugs e erros conhecidos

| # | Severidade | Descrição | Evidência |
|---|---|---|---|
| B1 | Média | O datatable consulta `DB::table('highlight')`, que é a **view SQL** `highlight` (não a tabela `highlights`). A listagem funciona, mas o grid não recebe `text_button`, `url`, `status_button`, `layout` nem `is_blank`, e o `value` exibido (row_number por `status DESC`) não acompanha o `ORDER BY created_at DESC` da view. | `v6/app/Http/Controllers/Prefecture/DatatableController.php:58` × `v6/database/migrations/2025_03_31_212620_create_view_highligh_table.php` |
| B2 | **Alta** | O slug do módulo na tabela `modulos` é `detaques` (typo). Qualquer consumidor de `modulos.slug` (permissões, URLs, relatórios) não encontra o módulo. | `v6/database/migrations/2024_11_01_150206_create_modulos_table.php:355` |
| B3 | **Alta** | `modulos.status = 0` desabilita o item de menu "Destaques" no CMS. O módulo só é acessível por URL direta. | `v6/database/migrations/2024_11_01_150206_create_modulos_table.php:356` e `v6/app/Providers/MenuServiceProvider.php` |
| B4 | Média | `toggleStatus` devolve sempre a mensagem "O destaque foi desativado com sucesso.", inclusive quando ativa. | `v6/app/Http/Controllers/Prefecture/HighlightController.php:133` |
| B5 | Média | A exclusão em lote usa `ajax.generic.content.deleteAll`, que opera sobre `contents` — não funciona para destaques. | `v6/resources/views/prefecture/highlight/index.blade.php` e `v6/routes/basepro.php:141` |
| B6 | Média | `is_blank` é persistido mas nunca aplicado no portal (sem `target="_blank"`). | `v6/app/Http/Model/Prefecture/Highlight.php` vs. `v6/resources/views/portal/layouts/modelo1/home/destaque.blade.php` |
| B7 | Média | O `update` grava `$data['fullscreen']`, campo inexistente na tabela `highlights` (ignorado pelo `$fillable`). | `v6/app/Http/Controllers/Prefecture/HighlightController.php:84` |
| B8 | Média | `layout` é `varchar(255)` e é comparado com inteiro (`where('layout', 1)`, `== 1`); o PostgreSQL não faz cast implícito de `varchar` para `int` em `=`. **[NÃO VERIFICADO em runtime]** | `v6/app/Providers/ConfigHeaderServiceProvider.php:103` |
| B9 | Baixa | Mensagem de erro do campo `position` diz "Por favor, informe um título." | `v6/app/Http/Requests/HighlightRequest.php` |
| B10 | Baixa | `position` aceita `null` no controller (`required\|\|integer`), pois a regra real é `required|integer` — o `\|\|` é redundante. | `v6/app/Http/Requests/HighlightRequest.php` |
| B11 | Baixa | A tela de edição envia `content.category_contents_id` (coluna de `contents`) no `POST ajax.delete.files`; para destaques o valor é vazio. | `v6/resources/views/prefecture/highlight/edit.blade.php` |
| B12 | Baixa | `Highlight::create($request->all())` recebe o arquivo `UploadedFile` no array de entrada (descartado pelo `$fillable`). | `v6/app/Http/Controllers/Prefecture/HighlightController.php:36` |

## 2. Funcionalidades incompletas ou mortas

| Item | Situação |
|---|---|
| Tabela `highlights` | **Vazia** na base `prefeituras_v5` (0 linhas) e `archives.highlight_id` também (0 linhas). O módulo nunca foi usado em produção. |
| `is_blank` | Campo morto (não exposto no formulário nem aplicado na view). |
| `fullscreen` | Campo fantasma gravado no `update`. |
| `HighlightFactory` | Factory **vazia** — não serve como fixture de teste. |
| Galeria de destaques | A tela de edição importa `chargeGallery()`/`setupGallery()` do módulo de mídias, mas o destaque não tem galeria própria. |
| API JSON | Não existe endpoint de leitura de destaques para o portal/terceiros. |

## 3. Acoplamentos frágeis

| Acoplamento | Risco |
|---|---|
| Portal ↔ módulo `noticias` | O carrossel de destaques só aparece se `modulos['noticias']` estiver ligado; desligar notícias **esconde** os destaques. |
| CMS ↔ módulo `conteudo` | Reutiliza `ajax.generic.content.deleteAll` e `ajax.delete.files`, pensados para `contents`. |
| JS ↔ prefixo do CMS | `/cms/destaques/{id}/status` hardcoded em `v6/public/assets/js/custom/contents/highlight/datatable.js`. |
| Coluna `archives.highlight` × `archives.highlight_id` | Dois conceitos na mesma tabela; risco de confusão em qualquer refatoração. |
| `modulos.slug` × `menu_orders.slug` | `detaques` vs `destaques` — nomes diferentes para o mesmo módulo. |

## 4. Riscos de dados (migração de schema)

| Risco | Detalhe | Mitigação |
|---|---|---|
| Coluna `status` nullable | Trocar para `default false` exige `UPDATE highlights SET status = false WHERE status IS NULL` | Migrar antes de alterar o default |
| `layout` varchar | `varchar` → `tinyint` exige `CAST(layout AS INTEGER)` e checagem de valores não numéricos | Validar `SELECT DISTINCT layout FROM highlights` |
| `position` sem unicidade | Pode haver posições duplicadas após edições manuais | Índice único + rotina de reindexação |
| Arquivos órfãos | Apagar destaque não apaga o PNG | Evento `deleting` no model ou job de limpeza |
| `ON DELETE CASCADE` em `archives.highlight_id` | Perde o registro do arquivo sem que o operator perceba | Audit log antes do delete |

## 5. Perguntas em aberto para o negócio

1. O módulo deve voltar a aparecer no menu do CMS (`modulos.status = 1`)?
2. O slug deve ser corrigido para `destaques`? A correção quebra permissões já
   concedidas com o slug antigo?
3. `is_blank` deve passar a abrir o link em nova aba?
4. Deve existir **mais de um** destaque ativo por vez? Hoje o portal renderiza todos os
   ativos em um carrossel (`lightSlider`), mas o `layout` fullscreen é aplicado se
   **qualquer** destaque ativo tiver `layout = 1`.
5. O botão CTA deve respeitar `is_blank` ou o próprio `url` já é aberto em nova aba pela
   configuração do navegador?
6. Quem aprova a publicação de um destaque? Hoje basta a permissão `destaques.*`.

## 6. Mapa v5 → v6

| Aspecto | v5 | v6 | Impacto |
|---|---|---|---|
| Model `Highlight` | `v5/app/Http/Model/Prefecture/Highlight.php` | `v6/app/Http/Model/Prefecture/Highlight.php` | **Idêntico** |
| Controller | `v5/app/Http/Controllers/Prefecture/HighlightController.php` | `v6/app/Http/Controllers/Prefecture/HighlightController.php` | **Idêntico** |
| Form Request | `v5/app/Http/Requests/HighlightRequest.php` | `v6/app/Http/Requests/HighlightRequest.php` | **Idêntico** |
| Migration | `v5/database/migrations/2025_03_31_210313_create_highlights_table.php` | `v6/database/migrations/2025_03_31_210313_create_highlights_table.php` | **Idêntica** |
| Views do CMS | `v5/resources/views/prefecture/highlight/` | `v6/resources/views/prefecture/highlight/` | **Idênticas** (`diff -rq` sem diferenças) |
| Factory | `v5/database/factories/HighlightFactory.php` | `v6/database/factories/HighlightFactory.php` | **Idêntica** (vazia nas duas) |
| JS do grid | `v5/public/assets/js/custom/contents/highlight/datatable.js` | `v6/public/assets/js/custom/contents/highlight/datatable.js` | Presente nas duas |
| Tabela `modulos` | **Não existe** na v5 | Migration `2024_11_01_150206_create_modulos_table.php` | Novo: registry de módulos |
| Menu do CMS | `case 'destaques'` presente (`v5/app/Providers/MenuServiceProvider.php:287`) | `case 'destaques'` presente | Igual, mas na v6 o item é filtrado por `modulos.status` |
| Regra de menu | `if (has_access("$menu->slug.index"))` | `if (has_access(...) && $menu->modulo->status)` | **Mudança**: na v6 o menu depende do registry |
| `resources` | `v5/database/seeds/ResourcesTableSeeder.php:314` cria `destaques` | Registro `id = 75` com `modulo_id = 55` | Equivalente |
| Portal — carrossel | `v5/resources/views/portal/layouts/modelo1/home/destaque.blade.php (e equivalentes em modelo2..modelo6)` | `v6/resources/views/portal/layouts/modelo1/home/destaque.blade.php (e equivalentes em modelo2..modelo6)` | Presente nas duas |

**Resumo do mapa**: o módulo foi **copiado sem alterações** da v5 para a v6. A única
evolução no entorno foi a introdução do registry de módulos (`modulos`), que hoje
**desabilita** o acesso pelo menu — uma regressão funcional em relação à v5, onde o
item de menu aparecia apenas por `has_access`.

## 7. Checklist de correção rápida

- [ ] Migrar o grid para o model `Highlight` (ou ampliar a view `highlight` com as colunas
      `text_button`, `url`, `status_button`, `layout`, `is_blank`) (`DatatableController.php:58`)
- [ ] `modulos.slug`: `detaques` → `destaques` (migration ou `UPDATE` pontual)
- [ ] `modulos.status`: `0` → `1` para o módulo voltar ao menu
- [ ] Mensagem de sucesso do `toggleStatus` conforme a ação realizada
- [ ] Remover `$data['fullscreen']` do `update`
- [ ] Aplicar `is_blank` no `<a>` do carrossel do portal
- [ ] Apagar o arquivo físico ao excluir o destaque
- [ ] Preencher a `HighlightFactory`
- [ ] Escrever testes (ver `07-TESTES.md`)

## 8. Dívidas técnicas herdadas do legado

| Dívida | Onde | Impacto na reconstrução |
|---|---|---|
| Regras de validação dentro do controller | `v6/app/Http/Controllers/Prefecture/HighlightController.php:35` (increment/decrement de posição) | Levar para um Service transacional |
| Upload e persistência no mesmo método | `…/HighlightController.php:37-52` | Separar em Action/Service de mídia |
| `try/catch` genérico com `\Exception` | `…/HighlightController.php:54` | Perde o motivo da falha; usar logs e mensagens por tipo |
| Sem log de auditoria (`activity()`) | todo o controller | Rastreabilidade de quem publicou um destaque |
| Resposta JSON com mensagem fixa | `…/HighlightController.php:133` | Padronizar respostas (API Resource + `ProblemDetails`) |
| Ausência de `Policy` | — | Autorização espalhada em views e no datatable |
| Ausência de índice em `highlights.position` | — | Reordenação faz full scan em produção grande |
| Ausência de `SoftDeletes` | — | Exclusão definitiva, sem possibilidade de desfazer |

## 9. Verificação realizada

| Item | Resultado |
|---|---|
| `ls dossie_modules/destaques/` | 9 arquivos presentes |
| Caminhos citados (`grep -ohE '(v5\|v6)/...'`) | 0 inexistentes |
| Marcadores de placeholder | 0 ocorrências |
| Tamanho por arquivo | todos entre 96 e 258 linhas → o arquivo `08-GAPS-E-DIVIDAS.md` foi ampliado para ultrapassar o mínimo de 100 linhas |
| Dados no banco | `highlights` com 0 linhas; `archives.highlight_id` com 0 linhas; `modulos` com `detaques`/`status = 0` |
