# Configurações da Instituição — Resumo Executivo

> **Versão analisada:** `v6` (com `v5` como base comparativa)
> **Slug do módulo:** `configuracoes-da-instituicao` (tabela `modulos`, id 1, status ativo)
> **Natureza:** CMS (painel administrativo) com efeitos diretos no Portal (público)
> **Estado:** migrado v5 -> v6 (v6 acrescenta Dashboard/Google Analytics, Selos e `config.json`)

---

## 1. Objetivo

O módulo é a central de parametrização da prefeitura: um único formulário que
reúne os dados cadastrais da instituição (razão social, endereço, contatos),
os metadados de SEO, as imagens de marca, as opções de comportamento do portal,
as credenciais de e-mail/Recaptcha, o portal de transparência externo e os selos
institucionais. Serve ao operador do CMS (prefeito, secretaria, TI da prefeitura) que
precisa ajustar identidade, contatos e comportamento do site sem mexer em
código, e ao cidadão, que enxerga o resultado dessas chaves no portal público
(título, logo, endereço, expediente, links rápidos, menu interativo, avisos).

> Observação estrutural: este módulo **não possui controller, model ou tabela
> própria**. Ele é definido pelo **recurso** `resources.slug = 'configuracoes'`
> (`resources.modulo_id = 1`), pelo **slug de rota** `configuracoes` e pela
> **categoria** `category_configurations.slug = 'site'`. Ver
> [08-GAPS-E-DIVIDAS.md](08-GAPS-E-DIVIDAS.md) para a sobreposição com
> `../outras-configuracoes/`.

## 2. Efeito / Impacto

| Faixa | Efeito |
|---|---|
| Cidadão | Vê no portal o título, a descrição, a logo, o favicon, o endereço, o expediente, o telefone, o e-mail, o nome do prefeito, as seções de notícias/links rápidos/menu interativo e os selos institucionais. |
| Prefeitura (CMS) | Cadastra e mantém a identidade institucional e as opções globais do site em 8 abas; salva em um único POST. |
| Transparência e legalidade | `structure_type` define o perfil prefeitura/câmara; `email_lai`, `email_denuncia`, `email_ouvidoria` e `full_list_requests_disabled` controlam o fluxo de solicitações; `portal_transparencia_*` habilita a busca no portal fiscal externo. |
| Operação técnica | Grava `config.json` na raiz do projeto e altera SMTP, Recaptcha, ambiente e debug da aplicação inteira; habilita/desabilita a página de manutenção global do portal. |

## 3. Comportamento

- A tela é uma **única view** (`prefecture.configurations.configuracoes.edit`)
  com **8 abas** controlled por `?display=` implícito: Institucional, SEO,
  Imagens, Opções, Portal de Transparência Público, Selos, Mail, Dashboard.
- As abas são montadas por **faixas do campo `order`** de cada configuração
  (não por `key`), exceto Opções, que também seleciona 4 chaves pelo nome.
- Toda a tela é gravada por **um único endpoint**,
  `POST update.configuration` → `update.configurations.by.category`, com
  `category_configurations_id` = 1 (categoria `site`).
- A aba ativa é preservada após o save: o controller devolve
  `->with('display', $request->display)` e a view lê `session('display')`.
- A leitura exige `configuracoes.edit`; a gravação exige `configuracoes.edit`
  (a mesma permissão, embora o menu exija `configuracoes.index`).
- A aba **Mail** só aparece para quem tem `mail_recaptcha`; as abas **SEO**
  (bloco GA) e **Dashboard** só aparecem para quem tem `dashboard-config.index`,
  e só podem ser gravadas por quem tem `dashboard-config.edit`.
- Arquivos (logo, favicon, logo do rodapé, aviso de notícias, imagem de acesso
  rápido) são redimensionados para 275px ou 75px de altura e gravados em
  `storage/app/public/configuracoes/`.
- Ao salvar a categoria `site`, o controller reescreve `config.json` na raiz do
  projeto — arquivo lido **a cada request** por `config/app.php`,
  `config/mail.php` e `config/recaptcha.php`.

## 4. Como o Usuário Interage

**Operador (CMS)**

1. Menu lateral → *Configurações* (visível só com `configuracoes.index` **e**
   módulo `configuracoes-da-instituicao` ativo).
2. Tela `/cms/configuracoes/editar/configuracoes` com as 8 abas.
3. Preenche os campos, troca as imagens, marca os checkboxes (que enviam `0`
   escondido + `1` marcado) e clica em *Registrar*.
4. Volta para a mesma aba, com flash “Configurações salvas com sucesso”.

**Cidadão (Portal)**

- Página de manutenção (`pagina_em_manutencao` = 1) substitui o portal por
  `portal.manutencao.index` para visitantes não logados.
- Home sem bloco de notícias quando `noticias` = 0; sem seção de últimas
  notícias quando `ultimas_noticias` = 0; sem links rápidos quando
  `links_rapidos` = 0; sem botão de contato quando `contact_link` = 0.
- Bloco de previsão do tempo quando `codigo_tempo` está preenchido.
- Rodapé com endereço, expediente e (opcionalmente) número da versão.

## 5. Detalhes e Particularidades Técnicas

- Camadas: `Route` → `check.logged` → `ConfigurationController@editByCategory`
  → `GetInformationsPrefectureTrait::getConfiguration()` → `App\Prefecture\Configuration`
  → view Blade → (POST) `ConfigurationRequest` → `ConfigurationController@updateByCategory`
  → `configurations` + `config.json` + cache.
- O `ConfigurationRequest` monta as regras **dinamicamente**, com **uma query
  ao banco por campo enviado** (N+1).
- `configurations.key` **não tem índice único**; chaves duplicadas fazem o
  update gravar só a primeira ocorrência.
- O `config.json` é escrito no **formato posicional** (`config[0]`, `config[1]`,
  `config[2]`); arquivo ausente ou incompleto **derruba a aplicação**.
- Há um `echo` no controller (`"JSON file created successfully..."`) antes do
  redirecionamento, o que pode emitir saída antes dos cabeçalhos.
- Caches são invalidados por chave: `Cache::pull('structureType')` a cada item
  gravado e `Cache::pull(PortalTransparenciaService::CACHE_KEY)` para chaves
  `portal_transparencia_*`.
- Dependências: `cartalyst/sentinel` (permissões), `intervention/image`
  (redimensionamento), `spatie/laravel-activitylog` (log), `laravel/crypt`
  (segredo do GA).

## 6. Estrutura de Dados

| Objeto | Descrição |
|---|---|
| `configurations` | Tabela única de chave/valor; 57 linhas ativas na categoria `site`. |
| `category_configurations` | Categorias; `site` = id 1. |
| View `configuracoes` | View SQL que achata todas as categorias (usada pelo datatable). |
| `modulos` | Registro id 1 = `configuracoes-da-instituicao`. |
| `resources` | Registro id 9 = `configuracoes`, `modulo_id` = 1. |
| Chaves especiais | `selos_institucionais` e `selos_institucionais_url` (JSON) — criados sob demanda, ausentes no banco atual. |

Detalhamento completo em [02-MODELAGEM.md](02-MODELAGEM.md).

## 7. Como Testar

| Cenário | Resultado esperado |
|---|---|
| Salvar a aba Institucional com título vazio | Erro de validação (`required` + `max:100` + `min:3`). |
| Salvar com `structure_type` = `camara` | Perfil do módulo muda para Câmara; `Cache::pull('structureType')` é executado. |
| Marcar `pagina_em_manutencao` e acessar o portal deslogado | Renderiza `portal.manutencao.index`. |
| Salvar a aba Mail com SMTP alterado | `config.json` é reescrito; `config/mail.php` lê `$data->config[0]`. |
| Enviar Property ID do GA com letras | Flash “O Property ID deve conter apenas números.” e nada é gravado. |
| Enviar Service Account JSON sem `private_key` | Flash “A Service Account informada é inválida.” |
| Enviar `dashboard_widget_refresh_minutes` = 2000 | Flash de faixa (1..1440). |

Matriz completa em [07-TESTES.md](07-TESTES.md).

## 8. Migração para Laravel Moderno

- Extrair a “configuração” para uma tabela `settings` tipada (ou `spatie/settings`),
  com **índice único em `key`** e coluna `category_id`.
- Separar o blob em **tabelas de domínio**: `institution`, `mail_settings`,
  `recaptcha_settings`, `seo_settings`, `feature_flags`, `portal_transparency`,
  `institutional_badges`, `dashboard_settings`.
- Guardar segredos com `encrypted` casts (Laravel 11) em vez de `Crypt::encrypt`
  manual, e eliminar `config.json` em favor de `.env` + tabela de runtime.
- Transformar a view de abas em componentes Blade únicos e tipados, com validação
  por Form Request dedicado por aba (hoje uma regra dinâmica genérica).
- Introduzir Policies (`UpdateInstitutionSettings`) e remover a checagem de
  permissão espalhada no controller.

Detalhamento em [06-MIGRACAO-MODERNA.md](06-MIGRACAO-MODERNA.md).

## 9. Resumo Geral

“Configurações da Instituição” é o módulo que transforma o CMS em um painel de
configuração real do portal municipal. Ele não é um CRUD de entidades: é uma
camada de chave/valor genérica (`configurations`) cujo conteúdo é interpretado
por controllers, providers e views espalhados pelo portal. A tela é uma
única view com 8 abas montadas por faixas numéricas do campo `order`, e tudo é
gravado por um único POST que reconstrói, entre outras coisas, o arquivo
`config.json` lido no boot de cada request. Os efeitos públicos das chaves são
amplos e pouco óbvios: identidade e SEO no `<head>`, imagens de marca,
comportamento de notícias, links rápidos, menu interativo, página de manutenção,
transparência externa e anonimização de dados via IA. O principal risco técnico
do módulo é essa indirectividade: nada impede que uma chave seja gravada com
efeito inesperado em outro módulo, e o preço do acerto é a validação frágil
(baseada em `notnull`/`max_input`/`min_input` por campo), a ausência de índice
único em `key` e a dependência de um arquivo JSON fora do ciclo de versionamento.

---

## Í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 (57 chaves da categoria `site`) |
| `03-ROTAS-E-CONTROLADORES.md` | Rotas, controller, Form Request, permissões |
| `04-VIEWS-E-UX.md` | Abas, componentes Blade, JS, efeitos no portal |
| `05-REGRAS-E-PORTABILIDADE.md` | Regras não óbvias, armadilhas e acoplamentos |
| `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, sobreposição com `outras-configuracoes`, mapa v5 -> v6 |
