# Vereadores e Mandatos — Arquitetura

> Módulo `vereadores` (id 43 na tabela `modulos`). **Novo na v6.**

---

## 1. Visão geral das camadas

O módulo é um CRUD convencional do legado Laravel 5.5, **sem repository e sem
service**. O fluxo é:

```
Rota (web.php / basepro.php)
   └─> Middleware (check.site.manutention | check.route.permission + csrf)
        └─> Controller
             ├─> FormRequest (CityCouncilorRequest / MandateRequest / MandateCategoryRequest)
             ├─> Model Eloquent (CityCouncilor / Mandate / MandateCategory / CouncilmenMandates)
             │      └─> PostgreSQL (councilmen, mandates, mandate_categories, councilmen_mandates)
             ├─> Archive (App\Prefecture\Archive) + Storage (content/vereadores/{id}/)
             └─> View Blade (v6/resources/views/portal/layouts/modelo1..modelo6/
                            informacoes-instituicao/vereadores|mandates/
                            ou v6/resources/views/prefecture/councilmen|mandates)
```

Não há API JSON dedicada a vereadores. O único consumo externo é indireto: a view SQL
`requerimentos` (que faz `LEFT JOIN councilmen cm ON cm.id = c.councilmen_id`) e o
módulo VIAP (`viap.councilman_id`).

## 2. Diagrama do fluxo

```
                        ┌─────────────────────────────────────────────┐
                        │  PORTAL (público) — v6/routes/web.php:140-143│
                        └─────────────────────────────────────────────┘
                                        │
  GET /vereadores ──────────────────────┼──> Portal\CityCouncilorController@index
  GET /vereadores/{id} ─────────────────┘    Portal\CityCouncilorController@show
  GET /mandatos/ ─────────────────────────> Portal\MandatesController@index
  GET /mandatos/{category} ────────────────> Portal\MandatesController@show
                                                │
                                                ▼
                     CityCouncilor::with('archives','mandates')
                                ->where('status', true)->get()
                                                │
                     view("portal.layouts.{$template}.informacoes-instituicao.…")
                                                │
                                                ▼
             modelo1/informacoes-instituicao/vereadores/index.blade.php` e
             modelo1/informacoes-instituicao/vereadores/show.blade.php`
             (uma cópia por tema: modelo2 a modelo6)
             modelo1/informacoes-instituicao/mandates/index.blade.php` e
             modelo1/informacoes-instituicao/mandates/show.blade.php`
             (uma cópia por tema: modelo2 a modelo6)


                        ┌─────────────────────────────────────────────┐
                        │  CMS — v6/routes/basepro.php:214-219,160,164 │
                        └─────────────────────────────────────────────┘
                                        │
   resource vereadores ─────────────────┼──> Prefecture\CityCouncilorController
   resource mandatos ───────────────────┤    (Prefecture\MandateController)
   resource categorias-mandatos ───────┤    (Prefecture\MandateCategoryController)
   POST /cms/ajax/ajust-vereadores-mandato┘   (MandateController@ajustOrder)
                                        │
                     ┌──────────────────┴───────────────────┐
                     ▼                                      ▼
      Prefecture\Controller (base)                activity()  ← auditoria
      aplica 'check.route.permission'
                     │
                     ▼
   FormRequest → Model → DB::transaction → Archive/Storage → flash() → redirect
```

## 3. Lista de classes envolvidas

### 3.1 Controllers do portal

| Classe | Caminho | Papel |
|---|---|---|
| `App\Http\Controllers\Portal\CityCouncilorController` | `v6/app/Http/Controllers/Portal/CityCouncilorController.php` | `index()` lista vereadores ativos; `show()` exibe o perfil. |
| `App\Http\Controllers\Portal\MandatesController` | `v6/app/Http/Controllers/Portal/MandatesController.php` | `index()` lista categorias de mandato; `show()` lista os mandatos de uma categoria. `create/store/edit/update/destroy` são **métodos vazios** (só `//`). |
| `App\Http\Controllers\Admin\Controller` | `v6/app/Http/Controllers/Admin/Controller.php` | Base dos controllers do portal; fornece `getTemplateActived()` (linha 39) que decide o tema (`modelo1`..`modelo6`). |

### 3.2 Controllers do CMS

| Classe | Caminho | Papel |
|---|---|---|
| `App\Http\Controllers\Prefecture\CityCouncilorController` | `v6/app/Http/Controllers/Prefecture/CityCouncilorController.php` | CRUD de vereadores, upload de foto, atribuição/remoção de mandato, exclusão do arquivo de imagem. |
| `App\Http\Controllers\Prefecture\MandateController` | `v6/app/Http/Controllers/Prefecture/MandateController.php` | CRUD de mandatos, tela de ordenação dos vereadores do mandato, persistência da ordem. |
| `App\Http\Controllers\Prefecture\MandateCategoryController` | `v6/app/Http/Controllers/Prefecture/MandateCategoryController.php` | CRUD das categorias de mandato. |
| `App\Http\Controllers\Prefecture\Controller` | `v6/app/Http/Controllers/Prefecture/Controller.php` | Base do CMS; o construtor aplica o middleware `check.route.permission` (linha 22). |

### 3.3 Models

| Classe | Caminho | Tabela | Papel |
|---|---|---|---|
| `App\Http\Model\Prefecture\CityCouncilor` | `v6/app/Http/Model/Prefecture/CityCouncilor.php` | `councilmen` | Vereador. `SoftDeletes`. Relações: `mandates()` (belongsToMany), `archives()` (hasOne). |
| `App\Http\Model\Prefecture\Mandate` | `v6/app/Http/Model/Prefecture/Mandate.php` | `mandates` | Mandato. `SoftDeletes`. Relações: `categories()` (hasOne), `councilmen()` (belongsToMany). |
| `App\Http\Model\Prefecture\MandateCategory` | `v6/app/Http/Model/Prefecture/MandateCategory.php` | `mandate_categories` | Categoria de mandato. `SoftDeletes`. |
| `App\Http\Model\Prefecture\CouncilmenMandates` | `v6/app/Http/Model/Prefecture/CouncilmenMandates.php` | `councilmen_mandates` | Pivot. **Sem `SoftDeletes`**, apesar de a tabela ter `deleted_at`. |
| `App\Prefecture\Archive` | `v6/app/Http/Model/Prefecture/Archive.php` | `archives` | Arquivo (foto do vereador). Note o namespace `App\Prefecture` apesar do diretório. |
| `App\Http\Model\Prefecture\Content` | `v6/app/Http/Model/Prefecture/Content.php` | `contents` | Conteúdo genérico; expõe `councilman()` (belongsTo) via `contents.councilmen_id`. |
| `App\Http\Model\Prefecture\Viap` | `v6/app/Http/Model/Prefecture/Viap.php` | `viap` | Vínculo de gabinete; expõe `councilman()` (belongsTo) via `viap.councilman_id`. |

### 3.4 Form Requests

| Classe | Caminho | Valida |
|---|---|---|
| `App\Http\Requests\CityCouncilorRequest` | `v6/app/Http/Requests/CityCouncilorRequest.php` | `name`, `party`, `archives_id` (imagem). |
| `App\Http\Requests\MandateRequest` | `v6/app/Http/Requests/MandateRequest.php` | `mandate_categories_id`, `name`, `start_year`, `end_year`. |
| `App\Http\Requests\MandateCategoryRequest` | `v6/app/Http/Requests/MandateCategoryRequest.php` | `name`. |

### 3.5 Helpers e middleware

| Item | Caminho | Papel |
|---|---|---|
| `has_access()` | `v6/app/Library/Helper/appHelpers.php:22` | Autorização por permissão Sentinel; `super-admin` passa em tudo. |
| `menuClicks()` | `v6/app/Helpers/functions.php:865` | Incrementa `menu_orders.clicks` para o slug informado. |
| `str_slug()` | `illuminate/support` | Geração de slug a partir do nome. |
| `CheckRoutePermission` | `v6/app/Http/Middleware/CheckRoutePermission.php` | Bloqueia a rota CMS quando o usuário não tem a permissão correspondente ao nome da rota. |
| `CheckLogged` | `v6/app/Http/Middleware/CheckLogged.php` | Exige sessão autenticada (registrado em `v6/app/Http/Kernel.php:63`). |

### 3.6 Views

| Caminho | Papel |
|---|---|
| `v6/resources/views/portal/layouts/modelo1/informacoes-instituicao/vereadores/index.blade.php` (idem nos temas modelo2 a modelo6) | Lista pública de vereadores (cartões). |
| `v6/resources/views/portal/layouts/modelo1/informacoes-instituicao/vereadores/show.blade.php` (idem nos temas modelo2 a modelo6) | Perfil público do vereador. |
| `v6/resources/views/portal/layouts/modelo1/informacoes-instituicao/mandates/index.blade.php` (idem nos temas modelo2 a modelo6) | Categorias de mandato (menu lateral). |
| `v6/resources/views/portal/layouts/modelo1/informacoes-instituicao/mandates/show.blade.php` (idem nos temas modelo2 a modelo6) | Acordeão com os vereadores de cada mandato. |
| `v6/resources/views/portal/layouts/modelo5/home/vereadores/vereadores-carousel.blade.php` | Carrossel da home (tema `modelo5`). |
| `v6/resources/views/prefecture/councilmen/{index,create,edit,show,form}.blade.php` | CMS de vereadores. |
| `v6/resources/views/prefecture/mandates/{index,create,edit,form,edit-council-members}.blade.php` | CMS de mandatos + tela de ordenação. |
| `v6/resources/views/prefecture/mandate-categories/{index,create,edit,form}.blade.php` | CMS de categorias de mandato. |

## 4. Resolução do tema do portal

`getTemplateActived()` (`v6/app/Http/Controllers/Admin/Controller.php:39`) lê
`Configuration::where('key','layout')->first()->value` e aborta com 404 se a view da
home daquele tema não existir. Todos os controllers de portal deste módulo montam a
view assim:

```php
return view("portal.layouts.{$this->getTemplateActived()}.informacoes-instituicao.vereadores.index", compact('title', 'contents'));
```

Consequência prática: **cada tema tem sua própria cópia** das views. Alterar o layout
de vereadores exige replicar a mudança em `modelo1`..`modelo6`.

## 5. Dependências externas

| Pacote | Versão (v6/composer.json) | Uso no módulo |
|---|---|---|
| `laravel/framework` | `5.5.*` | Eloquent, Form Requests, Blade, Storage. |
| `cartalyst/sentinel` | `2.0.*` | Autenticação e permissões (`has_access`, `Sentinel::getUser()`). |
| `intervention/image` | `^2.7` | Manipulação de imagem (upload da foto do vereador). |
| PostgreSQL 10 + PostGIS | — | Banco de dados; view SQL `requerimentos`. |
| jQuery + jQuery UI (`sortable`) | — | Ordenação por arrastar e soltar na tela de ordenação dos vereadores do mandato. |
| lightSlider | — | Carrossel da home no tema `modelo5`. |
| Summernote | — | Editor WYSIWYG do campo "texto" (biografia). |
| AdminLTE 1.22 / Bootstrap 4 | — | respectively CMS e portal. |
