# Requerimentos — Resumo Executivo

> **Versão analisada:** `v6` (Laravel 5.5.50 / PHP 7.2.34 / PostgreSQL 10)
> **Slug do módulo:** `requerimentos` (tabela `modulos`, id 41)
> **Natureza:** Ambos (portal público + CMS AdminLTE)
> **Estado:** **NOVO na v6** — não existe equivalente na v5
> **Módulo desligado por padrão:** `modulos.status = false` no seed; ligado em `/cms/modulos`

---

## 1. Objetivo

O módulo **Requerimentos** publica no portal os requerimentos encaminhados pelos
vereadores à Câmara Municipal, permitindo ao cidadão consultar e pesquisar
(por ano, mês e texto) o histórico de proposituras. No painel administrativo o
operador cadastra requerimentos dentro de **categorias** (por exemplo, “Requerimento
de Informação”, “Requerimento de Urgência”), informa o **requerente** (vereador),
o **texto** e anexa arquivos de apoio (PDF, DOC, planilhas). O módulo serve à
transparência do processo legislativo e ao atendimento ao cidadão.

## 2. Efeito / Impacto

| Faixa | Efeito |
|---|---|
| Cidadão | Acesso público a todos os requerimentos publicados, com busca por ano/mês/texto, paginação e download dos anexos |
| Prefeitura (CMS) | Cadastro de requerimentos, subcategorias e vínculo com o vereador requerente; telemetria de clique no menu |
| Transparência e legalidade | Publicação do que foi requerido, com autor (vereador), data e texto integral |
| Operação técnica | Módulo é conteúdo genérico (`contents`) + view SQL `requerimentos`; sem tabela própria |

> Observação: o item “Transparência e legalidade” acima descreve o efeito
> pretendido do módulo; a implementação atual depende de uma view SQL mantida
> por quatro migrations (ver `02-MODELAGEM.md`).

## 3. Comportamento

- `GET /requerimentos` **redireciona** para a primeira subcategoria da raiz
  `requerimentos` (ordem por `order`); se não houver subcategorias, usa a própria
  raiz; se a raiz não existir, redireciona para `/` com mensagem de erro.
- A listagem **unifica todas as subcategorias**: o slug da URL serve apenas para
  marcar a aba ativa e o título; o conjunto de resultados é sempre o mesmo
  (todas as categorias filhas da raiz).
- Filtros: `ano` (`whereYear`), `mes` (`whereMonth`) e `texto` (busca
  insensível a acentos em `title` e `text`, via `translate(...) ilike`).
- Conteúdos com `publication_date` futura **não aparecem** na listagem.
- Cada abertura de um requerimento incrementa `contents.clicks` em 1.
- Anexo marcado como `view_pdf` é embutido em `<iframe>`; os demais anexos de
  extensões permitidas viram links de download.
- No CMS, o requerente é um vértice de `councilmen` (FK `contents.councilmen_id`),
  exibido na listagem do painel e na coluna `requerente` da view SQL.

## 4. Como o Usuário Interage

**Cidadão (portal)**

1. Acessa `/requerimentos` e é levado à lista.
2. Escolhe o ano, o mês e/ou digita um termo de busca; a lista é recarregada por
   Ajax (sem recarregar a página) e a página atual fica no `location.hash`.
3. Clica em um item e abre a página do requerimento (texto completo, data/hora
   de publicação, anexos).

**Operador (CMS `/cms/conteudos/requerimentos`)**

1. Lista em DataTable: título, requerente, categoria, data de publicação, ações.
2. Botões “Categorias de Requerimento” e “Cadastrar Requerimento”.
3. Formulário: categoria (select), título, data de publicação (data+hora),
   requerente (select de vereadores ativos), texto (Summernote) e arquivos.
4. Exclusão em lote pela caixa de seleção da tabela.

## 5. Detalhes e Particularidades Técnicas

- Camadas: `Route` → `Portal\RequerimentoController` → `Content`/`CategoryContent`
  (Eloquent) → `contents`/`category_contents` → Blade do tema ativo.
- O CMS **não tem controller dedicado**: usa o CRUD genérico
  `Prefecture\ContentController` com o slug `requerimentos`.
- A listagem do CMS lê a **view SQL** `requerimentos`
  (`DB::table('requerimentos')->get()`), não a tabela `contents`.
- A view SQL foi recriada **4 vezes**; a versão vigente usa `WITH RECURSIVE`.
- Busca textual concatena `clean_slug($request->texto)` — porém com **binding
  `?`**, o que evita injeção SQL (diferente do padrão usado em
  `Portal\AtasEPontosController`, que concatena direto na string).
- O bloco de filtros/Ajax está **duplicado** em `modelo1`…`modelo6`.
- `row_number()` na view não é estável entre requisições.
- Dependências: `cartalyst/sentinel` (permissões), `yajra/laravel-datatables-oracle`
  (DataTable), PostgreSQL (view SQL).

## 6. Estrutura de Dados

| Objeto | Tipo | Papel |
|---|---|---|
| `contents` | tabela | Armazena os requerimentos (título, texto, data, slug, categoria, requerente) |
| `category_contents` | tabela (árvore) | Raiz `requerimentos` (id 37) e subcategorias |
| `councilmen` | tabela | Vereadores; origem do campo `requerente` |
| `archives` | tabela | Anexos (`view_pdf`, `highlight`, `extension`, `path`) |
| `requerimentos` | **view SQL** | Listagem do CMS (6 colunas) |
| `modulos` / `menu_orders` | tabelas | Módulo e telemetria de menu (`menu_orders.clicks`) |

## 7. Como Testar

- Portal: abrir `/requerimentos`, filtrar por ano/mês/texto, paginar, abrir um
  requerimento e conferir o incremento de `clicks`.
- CMS: listar, criar, editar, excluir (simples e em lote), criar subcategoria.
- Caso automatizado de referência: ver `07-TESTES.md`.

## 8. Migração para Laravel Moderno

Criar um **modelo próprio** `Requerimento` (tabela `requerimentos`) com
`requerente_id`, `category_id`, `published_at`, `status`, `body`, `slug`;
`Form Request` para validação; `Policy` por papel; `API Resource` JSON;
rotas REST sob `/api/requerimentos`; testes Pest/PHPUnit. Manter
incondicionalmente: filtros por ano/mês/texto, unificação de categorias,
ocultação de conteúdo futuro, incremento de `clicks` e download de anexos.

## 9. Resumo Geral

Requerimentos é um módulo **novo na v6** que publica proposituras de vereadores
no portal. Ele não possui tabela própria: reaproveita `contents` (com
`councilmen_id` como requerente) e `category_contents` (árvore de subcategorias),
e expõe uma **view SQL** `requerimentos` mantida por quatro migrations — a
vigente usa `WITH RECURSIVE` sobre a árvore de categorias e um `LEFT JOIN`
opcional em `councilmen`. No portal, a listagem unifica todas as subcategorias e
filtra por ano, mês e texto (com normalização de acentos via `translate(...)`),
pagina 12 por página via Ajax e esconde conteúdos com data futura. Cada
visualização incrementa `clicks`. No CMS, o CRUD genérico de conteúdos valida o
requerente contra `councilmen`, exige título, texto, categoria e data, e a
listagem do painel é alimentada pela própria view SQL. As permissões
`requerimentos.create/edit/delete` só existem para o papel `super-admin` no
ambiente analisado. Para a v7, recomenda-se um modelo dedicado, com
`Form Request`, `Policy` e API JSON, preservando o comportamento observável.

---

## Í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, permissões |
| `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 |
