# Requerimento de Diárias — Arquitetura

## 1. Visão geral das camadas

```
Request HTTP
   │
   ├── /cms/requerimento-diarias*  ─► middleware 'check.route.permission'
   │        │                           (v6/app/Http/Middleware/CheckRoutePermission.php)
   │        ▼
   │   Prefecture\RequerimentoDiariasController
   │        ├── RequerimentosRequest (validação do store)
   │        ├── RequerimentoRepository (upInsert / destroyAll / generatePDF)
   │        ├── Model RequerimentoDiarias / RequerimentoDiariasConfig
   │        └── Model Archive (App\Prefecture\Archive)
   │        ▼
   │   PostgreSQL: requerimento_diarias, requerimento_diarias_configs,
   │                archives, servidor, states  +  view req_diarias
   │
   └── /requerimento-de-diarias* ─► middleware 'check.site.manutention'
            │                      (v6/app/Http/Middleware/CheckSiteManutention.php)
            ▼
        Portal\BuscaDiariasController
            ├── DiariasRequest (validação dos filtros)
            ├── RequerimentoRepository (generatePDF)
            ├── Model RequerimentoDiarias (Eloquent + with)
            └── View portal.layouts.busca-diarias.show
```

## 2. Classes envolvidas

| Classe | Caminho | Papel |
|---|---|---|
| `Prefecture\RequerimentoDiariasController` | `v6/app/Http/Controllers/Prefecture/RequerimentoDiariasController.php` | CRUD do CMS, upload de arquivo, configurações, exclusão em lote |
| `Portal\BuscaDiariasController` | `v6/app/Http/Controllers/Portal/BuscaDiariasController.php` | Listagem pública com filtros e detalhe em PDF |
| `Prefecture\DatatableController` | `v6/app/Http/Controllers/Prefecture/DatatableController.php:179-183` | Endpoint JSON do DataTable do CMS (`get_requerimentos_diarias`) |
| `RequerimentoRepository` | `v6/app/Repositories/Eloquent/Prefecture/RequerimentoDiarias/RequerimentoRepository.php` | CRUD genérico herdado + `structureUpInsert` + `generatePDF` |
| `Repository` (abstrato) | `v6/app/Repositories/Repository.php` | `upInsert`, `destroy`, `destroyAll`, `dataTrait` |
| `AppTrait` | `v6/app/Http/Traits/AppTrait.php` | `filter_request` (linha 523), `traitRequest` (linha 658) |
| `IRequerimentoRepository` | `v6/app/Repositories/Contracts/IRequerimentoRepository.php` | Contrato **vazio** (sem métodos) |
| `RequerimentoDiarias` | `v6/app/Http/Model/Prefecture/RequerimentoDiarias.php` | Model da tabela `requerimento_diarias` (SoftDeletes) |
| `RequerimentoDiariasConfig` | `v6/app/Http/Model/Prefecture/RequerimentoDiariasConfig.php` | Model da tabela `requerimento_diarias_configs` (SoftDeletes) |
| `App\Prefecture\Archive` | `v6/app/Http/Model/Prefecture/Archive.php` | Model de `archives` (tabela compartilhada) |
| `App\Http\Model\Prefecture\Servidor` | `v6/app/Http/Model/Prefecture/Servidor.php` | Servidor requerente |
| `App\Admin\State` | `v6/app/Http/Model/Admin/State.php` | UF de destino (`App\Admin\State`, autoload por classmap) |
| `RequerimentosRequest` | `v6/app/Http/Requests/RequerimentosRequest.php` | Regras do cadastro/edição no CMS |
| `DiariasRequest` | `v6/app/Http/Requests/DiariasRequest.php` | Regra mínima de filtro do Portal (`cpf` min 14) |
| `RequerimentosConfigsRequest` | `v6/app/Http/Requests/RequerimentosConfigsRequest.php` | **Não é usado** pelo controller de configurações (que recebe `Request` cru) |
| `SelectRule` | `v6/app/Rules/SelectRule.php` | Regra que rejeita valor `'0'` em selects |
| `GetInformationsPrefectureTrait` | `v6/app/Http/Traits/GetInformationsPrefectureTrait.php:92` | `getTemplateActived()` — escolhe o layout do Portal |
| `Admin\Controller` | `v6/app/Http/Controllers/Admin/Controller.php` | Base do `BuscaDiariasController` (fornece `getTemplateActived`) |
| `Prefecture\Controller` | `v6/app/Http/Controllers/Prefecture/Controller.php` | Base do controller CMS; aplica `check.route.permission` no construtor |

## 3. Fluxo detalhado

### 3.1 CMS — criação (`POST /cms/requerimento-diarias`)

1. `check.route.permission` valida login e permissão
   (`hasAnyAccess(['requerimento-diarias.store'])` via nome da rota).
2. `RequerimentosRequest` valida os campos (todos `required`).
3. `RequerimentoDiariasController@store` chama
   `$this->repository->upInsert($request)`.
4. `Repository@upInsert` → `dataTrait` → `traitRequest` → `structureUpInsert`
   (normaliza datas) → `filter_request` → `updateOrCreate(['id' => null], $data)`.
5. Se houver `padrao_arquivo_config` ou upload, o controller grava um registro
   em `archives` com `requerimento_id`.
6. Redirect para `requerimento-diarias.index` com flash de sucesso.

### 3.2 CMS — listagem (DataTable)

1. `GET /cms/datatable/requerimento_diarias` → `DatatableController@get_requerimentos_diarias`.
2. `DB::table('req_diarias')->get()` — lê a **view SQL**, não a tabela.
3. `struct_views($data, 'requerimento-diarias')` injeta `edit`, `delete`,
   `active`, `inactivate` conforme `has_access()`.
4. `DataTables::of(...)->make(true)` devolve JSON.

### 3.3 Portal — busca

1. `GET|POST /requerimento-de-diarias` → `Portal\BuscaDiariasController@index`.
2. `DiariasRequest` valida `cpf` (mínimo 14 caracteres, nullable).
3. Query Eloquent `RequerimentoDiarias::with('servidor','archives')->orderBy('created_at','desc')`.
4. Filtros aplicados por `whereRaw`/`where` (ver `05-REGRAS-E-PORTABILIDADE.md`).
5. `paginate(10)` e render da view `portal.layouts.busca-diarias.show`.

### 3.4 Portal/CMS — PDF

1. `RequerimentoRepository@generatePDF($id, $hiddendados = false)`.
2. Lê `configurations`: `favicon`, `estado`, `titulo_site`, `cidade`.
3. Monta cabeçalho institucional e a tabela do requerimento.
4. `\PDF::loadView('prefecture.contents.requerimento-diarias.pdf.index', ...)->stream(...)`
   (DomPDF), nome do arquivo `diaria_requerimento_d_m_Y.pdf`.

## 4. Dependências externas

| Pacote | Versão (v6/composer.json) | Uso |
|---|---|---|
| `barryvdh/laravel-dompdf` | `^0.8.7` | Alias global `PDF` (`v6/config/app.php:273`) |
| `dompdf/dompdf` | `^0.8.3` | Motor de renderização do PDF |
| `tecnickcom/tcpdf` | `^6.3` | Presente no projeto, **não usado** por este módulo |
| `yajra/laravel-datatables` | ver `v6/composer.json` | DataTable do CMS |
| `cartalyst/sentinel` | ver `v6/composer.json` | Autenticação e permissões |
| `laravelcollective/html` | ver `v6/composer.json` | `Form::open` / `Form::close` nas views |

> `v6/composer.json` não lista `sweetalert2` explicitamente; o asset é carregado
> pelo layout AdminLTE (`public/assets/plugins/`). `[NÃO VERIFICADO]` a origem
> exata do asset de SweetAlert.

## 5. Onde o módulo se acopla ao restante do sistema

| Depende de | Onde |
|---|---|
| `servidor` (cadastro de servidores) | `id_servidor` do requerimento; select no formulário |
| `states` (UF) | `estado_destino`; select no formulário |
| `archives` (tabela global de arquivos) | Anexo da lei do requerimento |
| `configurations` | `favicon`, `estado`, `titulo_site`, `cidade`, `layout` no PDF e no layout do Portal |
| `modulos` / `resources` / `menu_orders` | Registro do módulo (id 36) e permissões |
| `Portal\RequerimentoController` (`v6/routes/web.php:44-46`) | **Módulo diferente** — rotas `/requerimentos*` cujas categorias (`category_contents.slug = 'requerimentos'`) pertencem ao módulo 41. Não confundir com `/requerimento-de-diarias*` |

## 6. Diagrama de sequência (Portal)

```
Cidadão ──POST /requerimento-de-diarias──► BuscaDiariasController@index
                                              │
                    ┌─────────────────────────┴──────────────────────┐
                    │ DiariasRequest (cpf min 14)                    │
                    │ RequerimentoDiarias::with(servidor, archives)  │
                    │ + filtros whereRaw                            │
                    └─────────────────────────┬──────────────────────┘
                                              ▼
                        portal.layouts.busca-diarias.show
                        (layout = portal.layouts.<modelo>.layout.layout)
                                              │
Cidadão ──GET /requerimento-de-diarias/{id}──► BuscaDiariasController@show
                                              ▼
                        RequerimentoRepository@generatePDF($id, true)
                                              ▼
                        PDF em streaming (CPF/identidade mascarados)
```

## 7. Estado do módulo no banco (verificado em `prefeituras_v5`)

| Tabela | Registros | Observação |
|---|---|---|
| `requerimento_diarias` | 0 | Ambiente sem dados de exemplo |
| `requerimento_diarias_configs` | 0 | Nenhuma configuração cadastrada |
| `req_diarias` (view) | 0 | Consistente com a tabela base |
| `resources` | 1 (`requerimento-diarias`, id 48, `modulo_id = 36`) | Define as permissões do módulo |
| `menu_orders` | 1 (`requerimento-diarias`, id 30, `modulo_id = 36`, `clicks = 96`) | Contador de acessos ao menu |

## 8. Anti-padrões presentes na arquitetura

1. **Interface de repositório vazia** — `IRequerimentoRepository` não declara
   nenhum método; o binding em
   `v6/app/Providers/RepositoryServiceProvider.php:92` (`$this->app->bind(IRequerimentoRepository::class, RequerimentoRepository::class)`)
   não agrega valor.
2. **Controller do CMS instancia o repositório manualmente**
   (`new RequerimentoRepository()`) apesar de também receber a interface por
   injeção — duas instâncias da mesma classe no mesmo objeto.
3. **Busca do CMS e do Portal usam fontes diferentes** (view SQL × Eloquent),
   garantindo divergência de colunas entre as duas telas.
4. **`Repository@upInsert` faz `dd($th)`** no `catch` — em produção o dump de
   exceção vaza stack trace ao operador.
