# Notícias

## O que é o módulo

Módulo de gerenciamento de notícias do portal. Permite criar, editar, arquivar e publicar notícias com fluxo de aprovação em 4 status (rascunho, pendente, publicado, rejeitado). Conta com notificações por e-mail para aprovadores, preview com token, SEO configurável, integração com busca full-text PostgreSQL (tsvector), sitemap Google News, e gerenciamento de configurações (sidebar, aprovadores).

## Estrutura de dados

### News (`v2_news`)
| Campo | Tipo | Descrição |
|-------|------|-----------|
| `id` | UUID (PK) | |
| `title` | string(255) | Título |
| `slug` | string(255) unique | Slug único |
| `subtitle` | string(500) nullable | Linha fina |
| `content` | text nullable | AST JSON do ContentRichEditor (Tiptap) |
| `summary` | text nullable | Resumo em texto puro |
| `status` | enum: draft/pending_approval/published/rejected | Status |
| `draft_token` | UUID nullable | Token para preview de rascunhos |
| `author_id` | string(36) nullable | FK para users |
| `reviewer_id` | string(36) nullable | FK para users (quem aprovou/rejeitou) |
| `published_at` | timestamp nullable | Data de publicação |
| `rejection_reason` | text nullable | Motivo da rejeição |
| `metadata` | jsonb nullable | SEO data + metadados flexíveis |
| `cover_image_id` | string(36) nullable | FK para v2_gallery_media |
| `search_vector` | tsvector | Índice de busca full-text (trigger) |
| `created_at` / `updated_at` | timestamp | |
| `deleted_at` | timestamp nullable | Soft delete |

### NewsApprover (`v2_news_approvers`)
| Campo | Tipo | Descrição |
|-------|------|-----------|
| `id` | UUID (PK) | |
| `user_id` | integer unsigned | FK para users (Sentinel V1) |
| `valid_from` | datetime nullable | Início da vigência |
| `valid_until` | datetime nullable | Fim da vigência |
| `created_by` | string(36) nullable | UUID do admin que criou |
| `created_at` / `updated_at` / `deleted_at` | timestamp | |

### NewsConfig (`v2_news_configs`)
| Campo | Tipo | Descrição |
|-------|------|-----------|
| `id` | UUID (PK) | |
| `key` | string(100) unique | Chave de configuração |
| `value` | jsonb nullable | Valor |
| `created_at` / `updated_at` | timestamp | |

## Dependências

- **ActivityLoggerService** (`V2\Services\ActivityLogger`) — auditoria de CRUD e fluxo de aprovação
- **SEOService** (`V2\Services\SEO`) — meta tags e SEO
- **ContentRichEditorRendererService** (`V2\Services\ContentRichEditor`) — renderização do conteúdo
- **MailService** (`V2\Services\MailService`) — envio de e-mails de notificação
- **CMSIndexerService / PublicIndexerService** (`V2\Services\Search`) — indexação de busca
- **GalleryMedia** (`V2\Services\Gallery\Models`) — imagem de capa
- **User** (`App\Admin\User`) — autor/revisor
- **Sentinel** — autenticação e usuário logado

## Tabelas

- `v2_news`
- `v2_news_approvers`
- `v2_news_configs`

## Arquivos existentes

### Migrations
- `Migrations/2026_07_08_000001_create_v2_news_table.php`
- `Migrations/2026_07_08_000002_create_v2_news_approvers_and_configs_table.php`

### Models
- `Models/News.php`
- `Models/NewsApprover.php`
- `Models/NewsConfig.php`

### Controllers
- `Controllers/NoticiasCmsController.php` — CRUD + preview + fluxo de aprovação + SEO
- `Controllers/NoticiasPortalController.php` — listagem pública + show + preview
- `Controllers/NoticiasConfigController.php` — config sidebar + aprovadores
- `Controllers/NoticiasSitemapController.php` — Google News Sitemap XML

### Services
- `Services/NewsNotificationService.php` — notificação por e-mail para aprovadores
- `Services/NewsSearchSender.php` — indexação nos mecanismos de busca (CMS + público)

### Requests
- `Requests/NewsRequest.php` — validação de criação/edição

### Routes
- `Routes/cms.php` — rotas CMS (CRUD, aprovação, arquivadas, config, SEO)
- `Routes/web.php` — rotas públicas (listagem, show, preview, sitemap)

### Views CMS
- `Views/cms/index.blade.php` — listagem de notícias
- `Views/cms/create.blade.php` — criação
- `Views/cms/edit.blade.php` — edição
- `Views/cms/preview.blade.php` — preview
- `Views/cms/archived.blade.php` — arquivadas
- `Views/cms/config/index.blade.php` — configurações
- `Views/cms/includes/styles.blade.php`
- `Views/cms/includes/scripts.blade.php`
- `Views/cms/includes/form.blade.php`
- `Views/cms/includes/_editor-content.blade.php`
- `Views/cms/includes/_confirm-modal.blade.php`

### Views Portal
- `Views/portal/index.blade.php` — listagem pública
- `Views/portal/show.blade.php` — detalhe da notícia

### Views Email
- `Views/emails/notification-content.blade.php`

### ModuleProvider
- `ModuleProvider.php` — configuração do módulo com 5 submódulos (Todas, Criar, Pendentes, Arquivadas, Configurações)

## Observações

- **Fluxo de aprovação:** notícias passam por 4 status; ao submeter para aprovação, e-mails são disparados para todos os aprovadores ativos (exceto o autor). Aprovação/rejeição não disparam e-mail.
- **Índice tsvector:** trigger PostgreSQL `trg_v2_news_search_vector` atualiza automaticamente a coluna `search_vector` em INSERT/UPDATE com pesos distintos (title=A, subtitle/summary=B, slug=C).
- **Preview:** rascunhos são acessíveis via `/noticia/{slug}/preview?token={draft_token}`.
- **Sitemap:** cache de 6 horas com purge forçado às 03:30; inclui notícias publicadas nos últimos 6 meses.
- **Soft delete:** notícias deletadas vão para arquivadas; é possível restaurar via `POST /{id}/restaurar`.
- **SEO:** metadados de SEO salvos em `metadata.seo` no JSONB, com fallback para title/subtitle/summary.
- **Rota de update:** usa `PUT|POST` (Laravel 5.5 não tem suporte a `PUT` em forms sem hack).
- **Cover image:** usa `GalleryMedia` do serviço de galeria; método `getCoverImageUrl()` monta URL pública.
