# Configurações da Instituição — Modelagem de Dados

> Categoria `site` (id 1) da tabela `configurations`. 57 configurações ativas.

---

## 1. Tabela `configurations`

Criada por `v6/database/migrations/2018_05_11_131302_create_configurations_table.php`.
Colunas verificadas com `\d configurations` no banco `prefeituras_v5`.

| Coluna | Tipo | Null | Default | Observação |
|---|---|---|---|---|
| `id` | integer | no | — | PK, `increments` |
| `title` | varchar(191) | no | — | Rótulo exibido no CMS |
| `description` | text | sim | — | Texto de ajuda (ícone `?`) |
| `small_description` | text | sim | — | Subtítulo renderizado como HTML |
| `placeholder` | varchar(191) | sim | — | Placeholder do input |
| `key` | varchar(191) | no | — | **Sem índice único** |
| `value` | text | sim | — | Valor (texto, JSON ou caminho de arquivo) |
| `type` | varchar(191) | no | — | `text`, `textarea`, `number`, `file`, `checkbox`, `select`, `password`, `richtext`, `json` |
| `order` | integer | sim | — | Define a aba (faixas numéricas) e a ordenação |
| `max_input` | integer | sim | — | `maxlength` do input e regra `max:` |
| `min_input` | integer | sim | — | `minlength` do input e regra `min:` |
| `category_configurations_id` | integer | no | — | FK → `category_configurations.id` (`configurations_category_configurations_id_foreign`) |
| `notnull` | boolean | sim | — | Marca obrigatoriedade |
| `status_create` | boolean | sim | — | Usado apenas no `ORDER BY` da view SQL |
| `created_at` | timestamp | sim | — | |
| `updated_at` | timestamp | sim | — | |
| `deleted_at` | timestamp | sim | — | Soft delete |

Índices: **apenas** `configurations_pkey`. Não há índice único em `key` nem em
`category_configurations_id`.

## 2. Tabela `category_configurations`

Criada por `v6/database/migrations/2018_04_10_131301_create_category_configurations_table.php`.

| Coluna | Tipo | Null |
|---|---|---|
| `id` | integer | no (PK) |
| `name` | varchar(191) | no |
| `slug` | varchar(191) | no |
| `status_create` | boolean | sim |
| `created_at` / `updated_at` / `deleted_at` | timestamp | sim |

Categorias semeadas em `v6/database/seeds/CategoryConfigurationsTableSeeder.php`:
`site`(1), `prefeitura`(2), `temas`(3), `outros`(4), `layout`(5), `covid`(6),
`barra-privacidade`(7), `dashboard`(8).

## 3. Ligação com o módulo

| Tabela | Registro | Valor |
|---|---|---|
| `modulos` | id 1 | `configuracoes-da-instituicao` / “Configurações da Instituição” / status ativo |
| `resources` | id 9 | `configuracoes` / `modulo_id` = 1 |
| `category_configurations` | id 1 | `site` / “Site” |
| `menu_orders` | — | `modulo_id` = 1 (coluna adicionada por `v6/database/migrations/2024_11_04_094157_add_modulo_id_to_menu_order_table.php`) |

`resources.modulo_id` foi criado por
`v6/database/migrations/2024_11_05_104026_add_modulo_id_to_resources_table.php`.

## 4. View SQL `configuracoes`

Criada por `v6/database/migrations/2023_04_17_144615_create_view_to_configuracoes.php`:

```sql
CREATE OR REPLACE view configuracoes
AS SELECT row_number() OVER (ORDER BY (c.status_create IS TRUE) DESC, c.created_at  ASC) AS value,
    c.title AS titulo,
    cc.slug as categoria,
    c.id,
    c.type as tipo
FROM configurations c
    join category_configurations cc on c.category_configurations_id = cc.id
WHERE c.deleted_at IS NULL
ORDER BY (c.created_at) DESC;
```

- **Aberta por:** `v6/app/Http/Controllers/Prefecture/DatatableController.php`
  (`get_configuracoes()`, linha 384), via `DB::table("configuracoes")`.
- **O que expõe:** todas as configurações de **todas** as categorias, com o
  `id` da linha como coluna `value` e o slug da categoria como `categoria`.
- **Limitação:** não é filtrável por categoria; o datatable do CMS lista as 87
  configurações ativas do sistema inteiro, sem filtro de módulo.

## 5. Lista completa das 57 chaves da categoria `site`

Valores verificados no banco `prefeituras_v5` (consulta direta em
`configurations` com `category_configurations_id = 1` e `deleted_at IS NULL`).

| id | order | key | type | title | notnull | max/min | valor no banco |
|---|---|---|---|---|---|---|---|
| 1 | 0 | `structure_type` | select | Tipo de instituição | t | — | (vazio) |
| 2 | 1 | `titulo_site` | text | Título do Site | t | 100/3 | Instituição Exemplo |
| 3 | 2 | `descricao` | textarea | Descrição | t | 150/0 | Site da Instituição de Exemplo |
| 4 | 3 | `cnpj` | number | CNPJ | f | 14/14 | (vazio) |
| 5 | 4 | `cep` | text | CEP | t | 15 | 58040-750 |
| 6 | 5 | `logradouro` | text | Logradouro | t | — | R. Dr. Osório Abath, 26 - Torre, João Pessoa - PB, 58040-750 |
| 7 | 6 | `numero` | text | Número | t | — | 26 |
| 8 | 7 | `bairro` | text | Bairro | t | — | Torre |
| 9 | 8 | `cidade` | text | Cidade | t | — | João Pessoa |
| 10 | 9 | `estado` | text | Estado | t | — | PB |
| 11 | 10 | `email` | text | E-mail da instituição | t | 50/3 | contato@exemplo.gov.br |
| 14 | 11 | `email_lai` | text | E-mail da LAI | f | 50/3 | (vazio) |
| 15 | 12 | `email_suporte` | text | E-mail de Suporte | — | — | suporte@maxima.inf.br |
| 16 | 13 | `telefone` | text | Telefone | t | — | (00) 000000000 |
| 17 | 14 | `telefone_2` | text | Telefone 2 | f | — | (vazio) |
| 18 | 15 | `expediente` | text | Expediente | t | 190/0 | Segunda à Sexta: De 07h às 12h 13h às 17h |
| 81 | 15 | `nome_prefeito` | text | Prefeito(a) | f | 50/3 | (vazio) |
| 19 | 16 | `palavras_chaves` | text | Palavras-chave | t | 160/0 | Instituição, Exemplo, Site |
| 20 | 17 | `incorporacao_head` | textarea | Incorporação de cabeçalho | f | 1000/0 | (vazio) |
| 21 | 18 | `incorporacao_rodape` | textarea | Incorporação de rodapé | f | 1000/0 | (vazio) |
| 22 | 19 | `logo` | file | Logo | — | — | `../assets/images/prefeitura-logo.png` |
| 23 | 20 | `favicon` | file | Favicon | f | — | `../assets/images/prefeitura-favicon.png` |
| 24 | 21 | `logo_rodape` | file | Logo Rodapé | f | — | `../assets/images/prefeitura-logo.png` |
| 25 | 22 | `aviso_noticias` | file | Imagem de aviso | f | 255/1 | `assets/images/aviso_noticias.png` |
| 26 | 23 | `imagem-acesso-rapido` | file | Imagem de acesso rapido | f | 255/1 | (vazio) |
| 27 | 24 | `codigo_tempo` | text | Código do Tempo | t | 10/0 | 231 |
| 83 | 24 | `response_time` | text | Prazo de resposta em dias | t | 3/1 | 20 |
| 28 | 25 | `licitacoes_url` | text | Central de Licitações | f | — | (vazio) |
| 29 | 26 | `noticias` | checkbox | Desabilitar notícias? | f | — | 0 |
| 30 | 27 | `pagina_em_manutencao` | checkbox | Ativar página de manutenção? | — | — | 0 |
| 82 | 27 | `newsletters` | checkbox | Desabilitar Newsletter? | f | — | 0 |
| 31 | 28 | `links_rapidos` | checkbox | Exibir seção de links rápidos? | — | — | 1 |
| 84 | 28 | `contact_link` | checkbox | Habilitar link de formulário de Contato? | f | — | 0 |
| 32 | 29 | `ultimas_noticias` | checkbox | Exibir seção de últimas notícias/mais notícias? | — | — | 1 |
| 34 | 30 | `menu_interativo` | checkbox | Menu Interativo | t | — | 1 |
| 35 | 31 | `numero_versao` | checkbox | Exibir número da versão do site | — | — | 1 |
| 36 | 32 | `recaptcha_public_key` | text | Chave pública do Recaptcha | f | 150/0 | (vazio) |
| 37 | 33 | `recaptcha_private_key` | text | Chave privada do Recaptcha | f | 150/0 | (vazio) |
| 38 | 33 | `link_form_artist_registration` | text | Slug do Formulário de Cadastro de Artistas | — | 150 | (vazio) |
| 39 | 33 | `link_form_equipment_registration` | text | Slug do Formulário de Cadastro de Equipamentos | — | 150 | (vazio) |
| 40 | 36 | `app_env` | checkbox | Modo desenvolvimento | f | — | `prod` |
| 41 | 37 | `app_debug` | checkbox | Ativar debugbar | f | — | 0 |
| 42 | 38 | `mail_driver` | text | Driver | f | 50/0 | `smtp` |
| 43 | 39 | `mail_host` | text | Host | f | 50/0 | mail.maximatecnologia.com.br |
| 44 | 40 | `mail_port` | text | Porta | f | 50/0 | 465 |
| 45 | 41 | `mail_username` | text | Usuário | f | 80/0 | server_mail@maximatecnologia.com.br |
| 46 | 42 | `mail_password` | password | Senha | f | 80/0 | (preenchido) |
| 47 | 43 | `mail_encryption` | text | Criptografia | f | 80/0 | `ssl` |
| 48 | 44 | `mail_from_address` | text | Endereço | f | 80/0 | suporte@maxima.inf.br |
| 49 | 45 | `mail_from_name` | text | Nome do E-mail | f | 80/0 | Email Contato |
| 12 | 68 | `email_denuncia` | text | E-mail de Denúncia | f | 50/3 | (vazio) |
| 13 | 69 | `email_ouvidoria` | text | E-mail de Ouvidoria | f | 50/3 | (vazio) |
| 33 | 70 | `full_list_requests_disabled` | checkbox | Desabilitar listagem completa das solicitações? | f | — | 0 |
| 74 | 71 | `gemini_api_key` | text | Chave da API do Gemini | f | 255/0 | (vazio) |
| 85 | 80 | `portal_transparencia_ativo` | checkbox | Ativar Busca por Transparência Fiscal (Portal Externo) | f | — | 0 |
| 86 | 81 | `portal_transparencia_codigo_ente` | text | Código do Ente/Município | f | 50/0 | (vazio) |
| 87 | 82 | `portal_transparencia_url_portal` | text | URL do Portal Público | f | 255/0 | https://transparencia.elmartecnologia.com.br |

Observações:

- `notnull` em branco = coluna `NULL` no banco (não gravada pelo seed).
- `order` **não é único**: há colisões intencionais (15, 24, 27, 28, 33).
- Ordens 34, 35 e 46+ **não existem** na categoria `site`; a ordem 46 pertence a
  `layout` (categoria `temas`, id 3).

## 6. Chaves da categoria `dashboard` (id 8) usadas por este módulo

| order | key | type | Observação |
|---|---|---|---|
| 0 | `dashboard_enhanced_enabled` | checkbox | Liga o dashboard aprimorado |
| 1 | `google_analytics_property_id` | text | Só dígitos |
| 2 | `google_analytics_measurement_id` | text | Formato `G-XXXXXXX` |
| 3 | `google_analytics_sa_json` | textarea | JSON criptografado em repouso |
| 4 | `dashboard_widget_refresh_minutes` | text | 1..1440 |
| 5 | `dashboard_widgets_enabled` | text | JSON com a lista de widgets |

## 7. Chaves criadas sob demanda (ausentes no banco atual)

| key | Criada por | Conteúdo |
|---|---|---|
| `selos_institucionais` | `ConfigurationController@createSelosInstitucionais` (`category_configurations_id` = 1, `type` = `json`, `order` = 71) | JSON com `img`, `nome_original`, `titulo`, `url`, `posicao`, `nova_guia`, `descricao` |
| `selos_institucionais_url` | Gravado junto com a anterior | JSON com o array de URLs |

Verificado no banco: **nenhuma das duas existe** em `prefeituras_v5`.

## 8. Módulos e seeds

| Arquivo | O que faz |
|---|---|
| `v6/database/seeds/CategoryConfigurationsTableSeeder.php` | Cria as 8 categorias (`site` = id 1). |
| `v6/database/seeds/ConfigurationsTableSeeder.php` | 1125 linhas; semeia as 57 chaves da categoria `site` com `updateOrCreate`. |
| `v6/database/seeds/ResourcesTableSeeder.php` | Cria o recurso `configuracoes` ligado ao módulo 1. |
| `v6/database/migrations/2024_11_01_150206_create_modulos_table.php` | Cria a tabela `modulos`. |
| `v5/database/seeds/PrivacyBarSeeder.php` | Existia na v5 e foi removido na v6 (as 4 chaves da barra de privacidade migraram para `ConfigurationsTableSeeder.php`). |

## 9. Relacionamentos Eloquent

`v6/app/Http/Model/Prefecture/Configuration.php`:

```php
protected $table = 'configurations';

protected $fillable = [
    'key','value','status_create','type','title','category_configurations_id',
    'max_input','min_input','notnull','order','description','placeholder','small_description'
];

public function categoryConfiguration()
{
    return $this->hasOne(CategoryConfiguration::class, 'id', 'category_configurations_id');
}
```

Observações de modelagem:

- A relação é `hasOne` (não `belongsTo`); para o "belongsTo" use
  `categoryConfiguration->id`.
- Não há `$casts`: `notnull`, `max_input`, `min_input` e `order` chegam como
  strings do PostgreSQL e são comparados com `==` no código.
- Não há accessor para `type`, o que faz o `loop_config.blade.php` interpretar
  o tipo em condicionais Blade.
