# Manual do Sistema — Modelagem de Dados

> Estrutura de dados do módulo. Fonte: schema real do banco
> `prefeituras_v5` e migrations de `v6/database/migrations/`.

---

## 1. `manuals`

Criada por `v6/database/migrations/2023_01_20_162623_create_manuals_table.php`.

| Coluna | Tipo | Null | Default | Observação |
|---|---|---|---|---|
| `id` | integer | não | `nextval('manuals_id_seq')` | PK |
| `titulo` | varchar(191) | **não** | — | ex.: "Manual de Notícias" |
| `objetivo` | text | **não** | — | descrição textual do que o módulo faz |
| `url_portal` | varchar(191) | sim | — | link para a página equivalente no portal |
| `url_cms` | varchar(191) | sim | — | link para a tela equivalente no CMS |
| `deleted_at` | timestamp(0) | sim | — | `SoftDeletes` |
| `created_at` / `updated_at` | timestamp(0) | sim | — | |

Referenciada por: `manual_areas.manual_id` (FK).

## 2. `manual_areas`

Criada por `v6/database/migrations/2023_01_20_163012_create_manual_areas_table.php`.

| Coluna | Tipo | Null | Default | Observação |
|---|---|---|---|---|
| `id` | integer | não | seq | PK |
| `titulo` | varchar(191) | **não** | — | título da área |
| `archive_id` | integer | sim | — | **FK** -> `archives(id)` |
| `manual_id` | integer | **não** | — | **FK** -> `manuals(id)` |
| `descricao` | text | sim | — | HTML do Summernote |
| `deleted_at` | timestamp(0) | sim | — | `SoftDeletes` |
| `created_at` / `updated_at` | timestamp(0) | sim | — | |

> A migration `v6/database/migrations/2023_01_27_104631_add_area_to_manual_areas.php`
> tem um nome enganoso: apesar do nome, ela **não** altera
> `manual_areas` — insere uma área chamada "ATOS DA COMISSÃO DE LICITAÇÃO"
> na tabela `diario_areas` (módulo Diário Oficial). É uma migration
> fora de lugar.

## 3. `archives` (arquivo de destaque)

Usada via `App\Prefecture\Archive`. O `ManualAreaRepository` monta o
registro com:

```php
$archive = [
    0 => $uploadedFile,
    'extension' => $uploadedFile->getClientOriginalExtension(),
    'name'      => $nameFile,
    'title'     => $nameFile,
    'type'      => $uploadedFile->getMimeType(),
    'path'      => "/storage/manual-usuario/area/$resultado->id/destaque/$nameFile"
];
```

O `IArchiveRepository::upInsert`
(`v6/app/Repositories/Eloquent/Prefecture/Archive/ArchiveRepository.php`)
grava o arquivo em `storage/app/public/manual-usuario/area/{id}/destaque/`
e devolve o model, cujo `id` é gravado em `manual_areas.archive_id`.

## 4. `modulos` e `resources`

| Item | Valor |
|---|---|
| `modulos` | id **8**, name "Manual do Sistema", slug `manual-do-sistema`, `status = true` |
| `resources` | **NENHUMA LINHA** com slug `manual-usuario` |

O seeder `v6/database/seeds/ManualDoSistemaResourceSeeder.php` criaria o
recurso:

```php
Resource::updateOrCreate(
    ['slug' => 'manual-usuario'],
    [
        'name' => 'Manual do Sistema',
        'description' => 'Funcionalidade Manual do Sistema',
        'modulo_id' => 8,
        'created_at' => date("Y-m-d H:i:s")
    ]
);
```

Mas a linha **não existe** na base analisada — o seeder não foi executado
(ou foi sobrescrito por outra carga de `resources`). Consequência direta:
a permissão `manual-usuario.index` **não pode ser concedida** por nenhum
perfil, e `has_access('manual-usuario.create')` é falso para todos,
exceto `super-admin`.

## 5. Views SQL

**Nenhuma**. O módulo usa Eloquent diretamente.

## 6. Relacionamentos

```
Manual  --hasMany-->  ManualArea   (foreign key manual_id)
ManualArea --hasOne--> Archive     (chave estrangeira archive_id, id local)
ManualArea --belongsTo--> Manual
```

Ambos os models usam `SoftDeletes`, e o pivot não existe (relação 1:N).

## 7. Migrations e seeds

### 7.1 Migrations

| Migration | Efeito |
|---|---|
| `v6/database/migrations/2023_01_20_162623_create_manuals_table.php` | cria `manuals` |
| `v6/database/migrations/2023_01_20_163012_create_manual_areas_table.php` | cria `manual_areas` com as FKs |
| `v6/database/migrations/2023_01_27_104631_add_area_to_manual_areas.php` | **nome enganoso**: insere em `diario_areas` |
| `v6/database/migrations/2023_02_01_083626_add_itens_to_archives.php` | além do schema, **insere 20+ manuais** (dados em migration) |

### 7.2 Seeds

| Seed | Caminho | Efeito |
|---|---|---|
| `UpdateManualAreas` | `v6/database/seeds/UpdateManualAreas.php` | localiza manuais por título e cria as áreas correspondentes (Notícias, Avisos, Glossário, Agendas, LAI, Secretarias, Páginas Estáticas, Transparência Fiscal, Redes Sociais, Enquetes, Links Rápidos, Feriados Municipais, Mais Conteúdos, Menus do Site, Certificados, Revisões, Diário Oficial...) |
| `UpdateManualAreasDiarioSeeder` | `v6/database/seeds/UpdateManualAreasDiarioSeeder.php` | cria as áreas do "Manual do Diário Oficial" |
| `ManuaisSinergiaSeeder` | `v6/database/seeds/ManuaisSinergiaSeeder.php` | renomeia manuais de um título antigo para o novo (mapeamento `$oldTitle => $newTitle`) |
| `ManualDoSistemaResourceSeeder` | `v6/database/seeds/ManualDoSistemaResourceSeeder.php` | cria o recurso `manual-usuario` (modulo_id 8) — **não presente na base** |

### 7.3 Factories

| Factory | Caminho | Problema |
|---|---|---|
| `ManualFactory` | `v6/database/factories/ManualFactory.php` | aponta para `App\Manual::class` (classe inexistente) e não define atributos |
| `ManualAreaFactory` | `v6/database/factories/ManualAreaFactory.php` | aponta para `App\ManualArea::class` (classe inexistente) e não define atributos |

O model real é `App\Http\Model\Prefecture\Manual`; as factories legacy
usam `App\Manual` (o namespace antigo, antes da reorganização por
subdiretório).

## 8. Conteúdo semeado (amostra)

Títulos criados pela migration `2023_02_01_083626_add_itens_to_archives.php`:

| titulo | objetivo (resumo) |
|---|---|
| Manual de Notícias | "Cadastrar, deletar, atualizar e criar as Notícias do site." |
| Manual de Avisos | "Cadastrar, deletar, atualizar e criar os Avisos do site." |
| Manual de Glossário | "Cadastrar, deletar, atualizar e criar os Glossários do site." |
| Manual de Agendas | "Anunciar os eventos que ocorreram informando seu local e data..." |
| Manual de Solicitações(LAI) | "Cadastrar, deletar, atualizar e criar as Solicitações(LAI) do site." |
| Manual de Secretarias | "Cadastrar, deletar, atualizar e criar as Secretarias do site." |
| Manual da LGPD | "A LGPD tem por fim esclarecer ao usuário como seus dados serão utilizados." |
| Manual de Licitações | "Cadastrar, deletar, atualizar e criar as Licitações do site." |
| Manual de Órgãos | "Cadastrar, deletar, atualizar e criar os Órgãos do site." |
| Manual de Telefones Úteis | "Cadastrar, deletar, atualizar e criar as Telefones Úteis do site." |
| Manual do editor de imagens | "Facilitar a modificação de imagens especificas..." |
| Manual de Banners | "Cadastrar, deletar, atualizar e criar as Banners do site." |
| Manual de Legislação | "Cadastrar, deletar, atualizar e criar a Legislação do site." |
| Manual de Drive | "Cadastrar, deletar, atualizar e criar as imagens no drive." |
| Manual de Previsualização | "Facilitar Visualização do conteúdo como será exibido..." |
| Manual da Cidade | "Cadastrar, deletar, atualizar e criar as Informações de A Cidade." |
| Manual de Publicações | "Cadastrar, deletar, atualizar e criar as Publicações do site." |
| Manual de Menu | "Cadastrar, deletar, atualizar e criar os Itens do menu no site." |
| Manual da Instituição | "Cadastrar, deletar, atualizar e criar os dados de A Instituição no site." |

O `ManuaisSinergiaSeeder` renomeia alguns desses títulos (por exemplo,
"Manual de A Cidade" -> "Manual da Cidade").

## 9. Observações de modelagem para a v7

1. **`manuals.slug` deve existir.** Hoje o manual é identificado apenas por
   `titulo` (que é mutável — o `ManuaisSinergiaSeeder` renomeia). Um slug
   estável permitiria linkar o manual a um `modulos.id`.
2. **Vincular `manuals` a `modulos`.** O padrão de um manual por módulo
   existe (os títulos seguem os slugs dos módulos), mas nada garante a
   correspondência. Uma FK `modulo_id` eliminaria a duplicação de
   conhecimento.
3. **`descricao` deve ser `text` sanitizado**, não HTML livre. O
   Summernote permite `<script>`; a view renderiza com
   `@php echo ($area->descricao) @endphp` — **sem escape**. Isso é um risco
   de XSS armazenado (ver `05-REGRAS-E-PORTABILIDADE.md`).
4. **`archive_id` on delete**: apagar o arquivo na tabela `archives` deixa
   a área apontando para um id inexistente. Falta `onDelete('set null')` ou
   `cascade` na FK.
5. **Separar schema de dado**: os manuais devem ser criados por um
   **seeder**, não por uma migration.
