# Unidades de Atendimento — Resumo Executivo

> **Versão analisada:** `v6` (módulo **novo na v6** — inexistente na `v5`)
> **Slug do módulo:** `unidades-de-atendimento` (tabela `modulos`, id 47)
> **Natureza:** Ambos (CMS sob o prefixo `/cms` + portal público)
> **Estado:** novo na v6

---

## 1. Objetivo

O módulo publica a relação de **Unidades de Atendimento** da Prefeitura (unidades
de serviço, guichês, pontos de atendimento e(screen similar) Secretarias expostas
ao cidadão). Cada unidade é um *conteúdo* com título, texto, imagem de destaque,
galeria de fotos e link de vídeo (YouTube), listado em uma página pública
paginada. Serve ao cidadão que procura onde ser atendido e ao operador do CMS
que mantém a lista atualizada.

## 2. Efeito / Impacto

| Faixa | Efeito |
|---|---|
| Cidadão | Página pública `/unidades-de-atendimento` com grade de unidades (12 por página) e página de detalhe por unidade; link direto para o atendimento. |
| Prefeitura (CMS) | Tela "Lista de Unidades de Atendimento" com DataTable (ordenação, exportação Excel/PDF/CSV), cadastro, edição, galeria e exclusão em lote. |
| Transparência e legalidade | Divulga de forma estruturada a rede de atendimento; cada registro tem data de publicação e autor registrados. |
| Operação técnica | Reaproveita o contêiner genérico de `contents` + `category_contents`; o módulo não tem tabela própria, apenas uma view SQL de leitura para o CMS. |

## 3. Comportamento

1. A listagem pública busca a categoria `category_contents.slug = 'unidades-de-atendimento'`
   e retorna seus conteúdos **não deletados**, ordenados por `publication_date desc`
   e depois `id desc`, **paginados em 12 por página**
   (`v6/app/Http/Controllers/Portal/ServiceUnitsController.php:25-33`).
2. O detalhe busca por `contents.slug = {slug}` **restrito** a conteúdos da mesma
   categoria: a closure real é `whereHas('categoryContents', function ($query)
   use ($slug) { return $query->where('slug', 'unidades-de-atendimento'); })`.
   Com `firstOrFail()`, slug inexistente ou de outra categoria devolve 404
   (`v6/app/Http/Controllers/Portal/ServiceUnitsController.php:34-52`).
3. No detalhe, a galeria exibida é composta pelos `archives` do conteúdo **sem**
   imagem de destaque (`where('highlight', null)`).
4. O CMS é servido pelo controller genérico `Prefecture\ContentController`, que
   resolve a view pelo slug: `prefecture.contents.unidades-de-atendimento.*`
   (`v6/app/Http/Controllers/Prefecture/ContentController.php:115` e `:250-254`).
5. O slug da URL pública vem do título, gerado no `store`/`update`; se já existir
   conteúdo com o mesmo slug, é acrescentado `-<max(id)+1>`
   (`v6/app/Http/Controllers/Prefecture/ContentController.php:665-669`).
6. A listagem do CMS não consulta Eloquent: usa a **view SQL `unidades_de_atendimento`**
   (criada por migration) via `Prefecture\DatatableController@get_unidades_de_atendimento`
   (`v6/app/Http/Controllers/Prefecture/DatatableController.php:474-478`).

## 4. Como o Usuário Interage

**Cidadão (portal)**

- `GET /unidades-de-atendimento` → grade de cartões com miniatura, data
  (`d.m.Y`) e título (limitado a 50 caracteres em `modelo1`), paginação no rodapé.
- Clique no cartão → `GET /unidades-de-atendimento/{slug}` → título, autor/fonte,
  data/hora de publicação, imagem de destaque, texto HTML renderizado
  (`{!! $content->text !!}`) e galeria de fotos (lightgallery).
- Breadcrumb: Home › Unidades de Atendimento › [Unidade].

**Operador (CMS)**

- Menu lateral "Unidades de Atendimento" (ícone `home`) →
  `/cms/conteudos/unidades-de-atendimento` (`v6/app/Providers/MenuServiceProvider.php:295-297`).
- DataTable com colunas ID, Título e Ações; botões de galeria, editar e excluir;
  seleção múltipla com exclusão em lote; exportação para Excel, PDF e CSV
  (habilitada pela chamada real `runDatatables('unidades-de-atendimento',
  collums, true, 'ASC', null, true)`, em que o último argumento `true` liga o
  `deleteAll` da tabela).
- Botão "Cadastrar Unidade" abre `prefecture/contents/unidades-de-atendimento/create.blade.php`,
  que reaproveita o formulário de `noticias` (Summernote, upload de imagem,
  galeria opcional e vídeo do YouTube).

## 5. Detalhes e Particularidades Técnicas

- **Armadilha principal:** **não existe** um model `ServiceUnit` em `v6/app/Http/Model/Prefecture/`.
  O módulo usa `Content` (`App\Prefecture\Content`), `CategoryContent`
  (`App\Prefecture\CategoryContent`) e `Archive` (`App\Prefecture\Archive`).
  Qualquer reimplementação que crie um model "ServiceUnit" próprio rompe o
  contrato de dados com o CMS e com a view SQL.
- **Acoplamento forte ao contêiner genérico `contents`**: o módulo não tem
  tabela, model, repository ou controller próprio no CMS.
- **Layout do portal:** o controller resolve a view por
  `portal.layouts.{layout}.unidades-de-atendimento.*`, com `layout` vindo de
  `configurations.key = 'layout'` (`v6/app/Http/Traits/GetInformationsPrefectureTrait.php:92-102`).
- **Views só existem em `modelo1`..`modelo6`**; o layout `default` **não** possui
  a pasta do módulo — trocar o layout ativo sem criar as views quebra a rota.
- **Paginação fixa em 12** — não configurável pelo CMS.
- **N+1 evitado** no índice (`with('archives')`), mas as views usam
  `$content->archives[0]` sem `sortBy`, dependendo da ordem natural do banco.

## 6. Estrutura de Dados

| Objeto | Tipo | Observação |
|---|---|---|
| `category_contents` | tabela | Categoria raiz `slug = 'unidades-de-atendimento'` (id 44 no banco atual), `status_create = true`. |
| `contents` | tabela | Registros das unidades; FK `category_contents_id` NOT NULL. |
| `archives` | tabela | Arquivos (imagem de destaque `highlight = 1`, galeria `highlight = null`, PDFs). |
| `links` | tabela | Link único por conteúdo (vídeo YouTube) — `Content::linksUnique()`. |
| `unidades_de_atendimento` | **view SQL** | Projeção da listagem usada pelo CMS: `value, titulo, data_e_hora, id, galeria, slug`. |
| `modulos` | tabela | Registro do módulo (id 47). |
| `resources` | tabela | Recurso de permissão `unidades-de-atendimento` (id 66), `modulo_id = 47`. |
| `menu_orders` | tabela | Slug `unidades-de-atendimento`, `modulo_id = 47`, contagem de cliques. |

## 7. Como Testar

1. Criar uma categoria/unidade pelo CMS (`/cms/conteudos/cadastrar/unidades-de-atendimento`)
   e conferir `/unidades-de-atendimento` e `/unidades-de-atendimento/{slug}`.
2. Cadastrar 13+ unidades e verificar a paginação (12 por página).
3. Publicar uma unidade sem imagem de destaque e verificar o fallback
   `/storage/img/exemplos/sem-imagem.png`.
4. Testar slug inexistente → 404; slug de outra categoria → 404.
5. Conferir a DataTable do CMS e as exportações Excel/PDF/CSV.

## 8. Migração para Laravel Moderno

Extrair um model `ServiceUnit` **opcional** (mantendo `contents` como fonte da
verdade ou criando tabela própria com migração de dados), Form Requests
dedicados, Policy `ServiceUnitPolicy` no lugar das strings de permissão
`unidades-de-atendimento.*`, API Resource JSON e Blade components por layout.
A paginação de 12 deve virar constante configurável sem alterar o
comportamento padrão.

## 9. Resumo Geral

O módulo "Unidades de Atendimento" é uma **aplicação do contêiner genérico de
conteúdos**: não possui tabela nem model próprio. Uma categoria de conteúdo
(`category_contents.slug = 'unidades-de-atendimento'`) define o conjunto;
`contents` guarda título, texto, slug, data e galeria; `archives` guarda as
imagens. O portal publica a lista paginada (12 por página) e o detalhe, ambos
implementados por `Portal\ServiceUnitsController`; o CMS usa o
`Prefecture\ContentController` genérico e uma view SQL `unidades_de_atendimento`
para a DataTable. Os Slugs, a ordenação, a imagem de destaque e a galeria são
as regras que não podem mudar na reconstrução. O principal risco de migração é
tentar criar um model "ServiceUnit" isolado, perdendo a compatibilidade com
`contents`, `category_contents`, `archives` e com o restante do CMS.

---

## Í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 |
| `03-ROTAS-E-CONTROLADORES.md` | Rotas, controllers, requests, resources |
| `04-VIEWS-E-UX.md` | Telas, componentes, JS, assets |
| `05-REGRAS-E-PORTABILIDADE.md` | Particularidades e armadilhas |
| `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, comparativo v5 vs v6 |
