# Glossário — Gaps, Dívidas e Mapa v5 → v6

> Inventário do que está quebrado, morto ou divergente no módulo Glossário da `v6`,
> com o comparativo v5 → v6.

---

## 1. Bugs / erros conhecidos

| # | Severidade | Descrição | Evidência |
|---|---|---|---|
| B1 | Alta | **Layout `default` quebra `/glossario`.** `GlossaryController@index` renderiza `portal.layouts.{template}.transparencia.glossario`; o layout `default` só possui `pages/contents/glossario/show.blade.php` e não tem a pasta `transparencia` | `v6/app/Http/Controllers/Portal/GlossaryController.php:20-25` e `v6/resources/views/portal/layouts/default/` |
| B2 | Alta | **Busca global quebra nos layouts `default` e `newsbit`.** `getViewToBeReturned` devolve `glossario.show`, mas não existem `default/glossario/show.blade.php` nem `newsbit/glossario/show.blade.php` | `v6/app/Http/Controllers/Portal/PortalController.php:391-402` vs. `v6/resources/views/portal/layouts/` |
| B3 | Média | **Letra ignorada em `/portal/glossario/{letra}`.** O `contentList` redireciona sempre para `glossario.index`, descartando o parâmetro | `v6/app/Http/Controllers/Portal/PortalController.php:321` |
| B4 | Média | **Índice alfabético sensível a maiúsculas e acentos.** `where('title','like','A%')` no PostgreSQL é case-sensitive; termos com inicial acentuada ou minúscula ficam inalcançáveis pelo índice | `v6/app/Http/Controllers/Portal/GlossaryController.php:35` |
| B5 | Média | **Definição não é validada no servidor**, embora o formulário a marque como obrigatória | `v6/app/Http/Requests/ContentRequest.php:308-314` vs. `v6/resources/views/prefecture/contents/glossario/form.blade.php:16-24` |
| B6 | Média | **Verbetes desativados aparecem no portal.** A view SQL e o AJAX não filtram `status` | `v6/database/migrations/2023_04_10_151502_create_view_to_glossarios.php:16-25`, `GlossaryController.php:32-34` |
| B7 | Baixa | **Erro de AJAX silencioso.** O `error:` do `$.ajax` está vazio; a lista fica em branco sem mensagem | `v6/resources/views/portal/layouts/modelo1/transparencia/glossario.blade.php:59-61` |
| B8 | Baixa | **URL relativa no AJAX** (`glossario-ajax/{letra}`) quebra se o portal for publicado em subpasta | idem, linha 41 |
| B9 | Baixa | **`contentList` engole exceções** (`catch (\Throwable $th) {}`) e devolve resposta vazia com HTTP 200 | `v6/app/Http/Controllers/Portal/PortalController.php:367` |

## 2. Funcionalidades incompletas ou mortas

| # | Item | Situação |
|---|---|---|
| M1 | Dados do verbete | O formulário não expõe status, data de publicação, ordem, galeria, fonte, autor nem link: o operador não consegue "despublicar" um verbete, apenas excluir |
| M2 | Exportação | O portal não exporta; o CMS exporta via botões client-side do DataTable (Excel/PDF) herdados de `runDatatables` (`v6/public/assets/js/custom/utilities/table.js:29-33`) |
| M3 | Sinônimos / verbetes relacionados | Não há modelo de relação: o legado não oferece "ver também" |
| M4 | Termo sem inicial A–Z | O índice `range('A','Z')` não cobre Termo, Vowel ou Ç; verbetes iniciados por esses caracteres só aparecem em "all" |
| M5 | Paginação | A listagem pública carrega todos os verbetes de uma letra em um único JSON; sem paginação |

## 3. Itens existentes na v5 e removidos na v6 (ou o contrário)

| Item | v5 | v6 | Observação |
|---|---|---|---|
| `Portal/GlossaryController.php` | presente | presente | Código idêntico |
| `Prefecture/DatatableController::get_glossario` | presente | presente | Idêntico |
| Migration da view `glossario` | `v5/database/migrations/2023_04_10_151502_create_view_to_glossarios.php` | `v6/database/migrations/2023_04_10_151502_create_view_to_glossarios.php` | Mesmo nome e mesmo SQL |
| JS do DataTable | `v5/public/assets/js/custom/contents/glossario/datatable.js` | `v6/public/assets/js/custom/contents/glossario/datatable.js` | Idêntico |
| Views do portal | `v5/resources/views/portal/layouts/modelo1/transparencia/glossario.blade.php` (idem modelo2..modelo6) | `v6/resources/views/portal/layouts/modelo1/transparencia/glossario.blade.php` (idem modelo2..modelo6) | Idêntico |
| View de verbete | `v5/resources/views/portal/layouts/modelo1/glossario/show.blade.php` (idem modelo2..modelo6) | idem na v6 | Idêntico |
| Layout `default` | `v5/resources/views/portal/layouts/default/pages/contents/glossario/show.blade.php` | idem na v6 | Idêntico (e igualmente inacessível pelo controller) |
| Registro do módulo (`modulos`) | inexistente na v5 (tabela criada em 2024, na v6) | `v6/database/migrations/2024_11_01_150206_create_modulos_table.php:167-171` | Novo na v6 |

**Nenhum item do glossário foi removido na v6.** O que há é acúmulo: a v6 introduziu a
tabela `modulos`/`resources` (controle de acesso por módulo) sem eliminar o controle por
categoria de conteúdo.

## 4. Riscos de dados

| Risco | Descrição | Mitigação na v7 |
|---|---|---|
| DR1 | Migrar `contents` (categoria 11) para uma tabela própria exige mapear `title`->`term` e `text`->`definition` | Teste de migração com contagem e amostra |
| DR2 | A busca global e o mapa `getViewToBeReturned` referenciam o **id** 11 da categoria; renomear/reordenar ids quebra a busca | Passar a referenciar slugs |
| DR3 | Permissões são indexadas pelo slug `glossario` (`modulos.slug`, `resources.slug`) | Preservar o slug |
| DR4 | A view SQL `glossario` é consumida por `DB::table('glossario')`; se a view for removida o CMS quebra | Migrar para consulta Eloquent na v7 |
| DR5 | Soft delete: verbetes "excluídos" permanecem na base; restaurar exige intervenção manual | Manter `SoftDeletes` na v7 |

## 5. Dívidas técnicas

| Dívida | Onde | Impacto |
|---|---|---|
| D1 | O glossário reutiliza o CRUD genérico de `contents` (com dezenas de colunas não usadas) | Acoplamento e confusão de modelo |
| D2 | O JavaScript do índice alfabético está duplicado em 8 arquivos de portal | Correção precisa ser replicada |
| D3 | O JSON público devolve o model `Content` completo | Vazamento de dados e payload maior |
| D4 | O endpoint AJAX monta o filtro com concatenação de string em SQL (`like ''.$letter.'%'`) | O valor vem da URL; com `letter = '%'` o filtro é neutralizado (leitura de todos os verbetes) — não há sanitização |
| D5 | Sem cache: cada clique de letra gera uma consulta ao banco | Custo desnecessário em portal de alto tráfego |
| D6 | Sem índice sobre `contents.title` | Filtro por inicial pode varrer a tabela inteira |

## 6. Perguntas em aberto para o negócio

1. O glossário deve ter verbetes **inativos** (rascunho)? Hoje não há como despublicar um verbete sem apagá-lo.
2. Devem existir sinônimos/aliases para o mesmo termo (ex.: "Alíquota" e "Alíquota Tributária")?
3. O índice deve incluir letras acentuadas (Á, Ç, Ê) e números?
4. A ordenação dentro de uma letra deve ser alfabética? Hoje o AJAX não define ordenação (ordem do banco).
5. O glossário deve aparecer na busca global? Hoje aparece — e a pergunta responde "sim".
6. Quem é o responsável editorial pela curadoria dos verbetes?

## 7. Mapa v5 → v6

```mermaid
graph LR
  subgraph V5["v5 (Laravel 5.5 / PHP 7.2)"]
    A1["Portal/GlossaryController<br/>(index, showByLetterAjax)"]
    A2["Prefecture/DatatableController::get_glossario"]
    A3["view SQL glossario<br/>(migration 2023_04_10_151502)"]
    A4["views portal: modelo1..modelo6/transparencia/glossario<br/>modelo1..modelo6/glossario/show<br/>default/pages/contents/glossario/show"]
    A5["CMS: prefecture/contents/glossario/{index,create,edit,form}"]
  end
  subgraph V6["v6 (Laravel 5.5 / PHP 7.2)"]
    B1["Portal/GlossaryController<br/>(idêntico)"]
    B2["Prefecture/DatatableController::get_glossario<br/>(idêntico)"]
    B3["view SQL glossario<br/>(mesma migration)"]
    B4["views portal: mesmas cópias<br/>(idênticas)"]
    B5["CMS: mesmas views"]
    B6["NOVO: tabela modulos (id 24, slug glossario)"]
    B7["NOVO: resources.slug = glossario -> modulo_id 24"]
    B8["NOVO: menu do CMS 'Glossário' em MenuServiceProvider"]
  end
  A1 --> B1
  A2 --> B2
  A3 --> B3
  A4 --> B4
  A5 --> B5
  B6 --> B7 --> B8
```

**Resumo do mapa:** o módulo Glossário é **funcionalmente idêntico** entre v5 e v6. A v6
apenas adicionou a camada de registry (`modulos` + `resources` + menu), o que permite
habilitar/desabilitar o glossário por município e casar as permissões com outros módulos.
As bugs B1–B9 existem nas duas versões.

### Detalhamento das diferenças

| Dimensão | v5 | v6 |
|---|---|---|
| Controller do portal | `v5/app/Http/Controllers/Portal/GlossaryController.php` | `v6/app/Http/Controllers/Portal/GlossaryController.php` — sem alteração |
| Filtro por letra | `where('title','like',$letter.'%')` | idem |
| Source do CMS | `DB::table('glossario')` (view) | idem |
| View SQL | migration `2023_04_10_151502_create_view_to_glossarios.php` | idem |
| Views do portal | 8 arquivos de glossário | idem |
| Permissões | por categoria/conteúdo | por módulo `glossario` (id 24) + recurso `glossario` |
| Menu do CMS | item de menu genérico | item dedicado em `v6/app/Providers/MenuServiceProvider.php:271-273` |
| API | inexistente | inexistente |
| Testes | inexistentes | inexistentes |
