# 00 — Resumo: Módulo Diário Oficial

> Dossiê de referência para a reconstrução do portal municipal em PHP 8.x + Laravel 11/12.
> Base analisada: `v6/` (referência atual) com comparação `v5/` (versão anterior).

---

## 1. Objetivo do módulo

O **Diário Oficial Eletrônico** é o canal formal de publicação dos atos da
Prefeitura (atos do executivo, legislativo e judiciário, licitações, portarias,
decretos). O módulo cobre o ciclo completo:

1. Estruturação do conteúdo (áreas, subáreas, matérias textuais e anexos em PDF).
2. Composição de um **PDF paginado, com colunas, capa, cabeçalho, rodapé e
   assinatura digital**.
3. Publicação da edição no portal público, com busca, visualização embutida e
   download.
4. Rastreabilidade editorial: workflow de 4 olhos (rascunho → em revisão →
   publicado) e trilha de auditoria.

## 2. Efeito observável

| Quem | O que obtém |
|------|-------------|
| Operador do CMS | Lista de edições com status de workflow e de geração; cadastro/edição de diário, áreas, subáreas e matérias; upload de capa e de certificado A1/A3; preview do PDF; configurações globais (lei padrão, certificado padrão, posição do logo, imagem de cabeçalho). |
|Revisor | Publica a edição após a segunda pessoa revisar (princípio dos 4 olhos). O elaborador não pode publicar a própria edição. |
|Visitor do portal | Lista de edições publicadas, filtra por período/termo/edição, abre o PDF no navegador, consulta dados de assinatura digital, busca termo dentro do PDF, navega entre edições anterior/próxima e acessa a trilha de auditoria da edição. |

## 3. Estrutura de dados (resumo)

| Tabela | Papel |
|--------|-------|
| `diarios` | Edição do diário (cabeçalho, workflow, capa, status de geração do PDF) |
| `diario_areas` | Categorias de seção do diário (ex.: "Atos do Executivo") |
| `diario_sub_areas` | Subcategorias (ex.: "Portarias") — **não geram seção visual** |
| `diario_has_areas` | Matérias: título, HTML, anexo PDF, tipo, ordem, colunas |
| `diario_certificados` | Certificados digitais (`.pfx`/`.p12`) e material criptográfico |
| `diario_configs` | Configuração global (registro único, `id = 1`) |
| `archives` | Imagens de capa e de cabeçalho (compartilhada com o resto do sistema) |

Views PostgreSQL used pelo CMS: `diario_oficial`, `diario_oficial_pdf`,
`areas_do_diario`, `sub_areas_do_diario`.

Detalhes completos em `02-MODELAGEM.md`.

## 4. Arquitetura em uma linha

```
Rota (CMS, sob o prefixo /cms; ou portal, sob a raiz do site)
  → Controller (Prefecture\DiarioController ou Portal\DiarioController)
  → FormRequest (validação)
  → Repository (DiarioOficialRepository) ou Service (FPdfService + Pdf/*)
  → Model (App\Http\Model\Prefecture\Diario*)
  → PostgreSQL / storage
  → Blade + JS (DataTables, Summernote, viewer de PDF)
```

Detalhamento em `01-ARQUITETURA.md`.

## 5. Regras de negócio que NÃO podem mudar na v7

1. **A PDF nunca é gerado no `store`/`update`.** A edição é salva e o status de
   geração vai para `pending`. O PDF é produzido sob demanda, pelo botão
   "Processar PDF" do CMS (`GET /refresh-diario-preview/{id}`) ou pela visualização
   no portal.
2. **A assinatura digital só é aplicada quando o diário está publicado**
   (`status = true`). Rascunhos saem sem assinatura.
3. **A subárea não define seção.** Somente a **área** abre faixa de cabeçalho e
   quebra de página/coluna. Todo o conteúdo de uma área flui continuamente.
4. **`file_in = true`** rasteriza o PDF anexo (Imagick + Ghostscript) e o insere
   no fluxo de colunas; **`file_in = false`** importa as páginas do anexo uma a
   uma, cada uma ocupando uma página inteira do diário.
5. **O certificado do diário tem precedência** sobre o certificado padrão das
   configurações. Sem certificado disponível, a geração falha (retorna `false`).
6. **Workflow de 4 olhos:** só uma edição em revisão pode ser publicada, e o
   usuário que criou ou atualizou a edição não pode publicá-la.
7. **Soft delete em todas as tabelas** do módulo.

Regras detalhadas e armadilhas em `05-REGRAS-E-PORTABILIDADE.md`.

## 6. Particularidades técnicas

- Stack do legado: Laravel 5.5.50, PHP 7.2.34, PostgreSQL 10, Redis, APCu,
  Sentinel (`cartalyst/sentinel`), AdminLTE 1.22 (CMS) e Bootstrap 4 (portal).
- PDF: `setasign/fpdi` + `tecnickcom/tcpdf` 6.3; anexos convertidos com
  **Imagick + Ghostscript**; QR Code com `simplesoftwareio/simple-qrcode`.
- A leitura do certificado usa a CLI do OpenSSL (`openssl pkcs12`) via
  `shell_exec` — **risco de segurança registrado** em `08-GAPS-E-DIVIDAS.md`.
- O serviço de PDF do v6 é **monolítico** (`v6/app/Services/FPdfService.php`,
  374 linhas). Na v5 existiam 5 sub-serviços em `v5/app/Services/Pdf/`
  (`LayoutManager.php`, `HeaderRenderer.php`, `CoverHandler.php`,
  `ImageProcessor.php`, `PdfConverter.php`); o v6 removeu os três primeiros.
- O caminho do PDF gerado é
  `diario-oficial/content/{id}/pdf/diário-{edicao}.pdf` dentro do disco público
  do storage.

## 7. Como testar (resumo)

- Suíte: `php artisan test` (PHPUnit) na raiz de `v6/`.
- Cenários críticos: criação de edição; matéria textual com HTML; anexo PDF com
  `file_in` verdadeiro e falso; geração com 1/2/3 colunas; capa; assinatura
  digital; workflow de publicação; busca e filtro no portal; download do PDF.
- Detalhamento de casos em `07-TESTES.md`.

## 8. Migração para a v7 (resumo)

- Reescrever os 6 models com casts, enums e relações explícitas.
- Substituir as 4 views PostgreSQL por queries do Eloquent ou por
  `DatabaseView` do Laravel (mantendo o contrato de colunas consumido pelo
  DataTable).
- Extrair a geração de PDF para um **Job de fila** (`GenerateDiarioPdfJob`),
  eliminando o `pending` sem consumidor.
- Extrair a leitura do certificado para uma classe dedicada usando
  `proc_open` com argumentos em array (elimina a senha do log e o command
  injection).
- Plano detalhado em `06-MIGRACAO-MODERNA.md`.

## 9. Índice dos arquivos deste dossiê

| Arquivo | Conteúdo |
|---------|----------|
| `00-RESUMO.md` | Este resumo |
| `01-ARQUITETURA.md` | Fluxo da requisição, classes, diagrama, dependências |
| `02-MODELAGEM.md` | Tabelas, colunas, relações, views SQL, migrations, seeds |
| `03-ROTAS-E-CONTROLADORES.md` | Rotas CMS/portal, requests, resources, permissões |
| `04-VIEWS-E-UX.md` | Blades, layouts, JS/Ajax, portal vs CMS |
| `05-REGRAS-E-PORTABILIDADE.md` | Regras, acoplamentos, armadilhas, divergências v5 → v6 |
| `06-MIGRACAO-MODERNA.md` | Plano de reconstrução em Laravel 11/12 |
| `07-TESTES.md` | Estratégia, casos, fixtures, comandos |
| `08-GAPS-E-DIVIDAS.md` | Bugs, riscos, mapa v5 → v6, perguntas em aberto |

## 10. Documentação legada preservada

A pasta `90-LEGADO/` contém, **sem alterações**, os 28 arquivos markdown do
precedente `v6/wiki/modules/DiarioOficial/`. Eles são a fonte primária deste
dossiê e preservam detalhes que aqui foram sintetizados:

| Arquivo legado | Assunto |
|----------------|---------|
| `90-LEGADO/00-VISAO_GERAL.md` | Panorama do módulo e estrutura de diretórios |
| `90-LEGADO/01-MODELAGEM_DADOS.md` | DER e campos das 6 models |
| `90-LEGADO/02-ROTAS.md` | Rotas por arquivo |
| `90-LEGADO/03-CMS_LISTAGEM.md` | Listagem do CMS |
| `90-LEGADO/04-CMS_FORMULARIO.md` | Formulário do CMS |
| `90-LEGADO/05-CONTROLADORES.md` | Métodos dos 6 controllers |
| `90-LEGADO/06-REPOSITORIOS.md` | Repositórios e contratos |
| `90-LEGADO/07-SERVICO_PDF.md` | Serviço de PDF |
| `90-LEGADO/08-PORTAL_VISUALIZACAO.md` | Portal público |
| `90-LEGADO/09-FRONTEND_JS.md` | Frontend JS |
| `90-LEGADO/10-GESTAO_AREAS.md` | Áreas, subáreas e matérias |
| `90-LEGADO/11-CERTIFICADOS_CONFIG.md` | Certificados e configurações |
| `90-LEGADO/12-FLUXO_GERACAO_PDF.md` | Fluxo de geração |
| `90-LEGADO/13-MIGRACOES.md` | Histórico de migrations |
| `90-LEGADO/14-ARQUIVOS_COMPLETOS.md` | Conteúdo integral dos arquivos-chave |
| `90-LEGADO/15-ANALISE_PROBLEMA_PDF.md` | Análise do problema de colunas |
| `90-LEGADO/16-SOLUCAO_FINAL.md` | Solução final do layout em colunas |
| `90-LEGADO/17-MERGE_ANEXOS_PDF.md` | Merge de anexos por subárea |
| `90-LEGADO/18-SESSION_MERGE_ANEXOS.md` | Sessão de merge |
| `90-LEGADO/19-INVENTARIO_COMPLETO.md` | Inventário arquivo a arquivo |
| `90-LEGADO/20-SERVICOS_PDF.md` | Camada de serviços de PDF do v6 |
| `90-LEGADO/21-ROTAS_E_PERMISSOES.md` | Rotas e permissões Sentinel |
| `90-LEGADO/22-ANOMALIAS_E_RISCOS.md` | Catálogo de anomalias |
| `90-LEGADO/23-GUIA_EXECUCAO.md` | Guia de execução do módulo |
| `90-LEGADO/CadeiaDeErros_ColunasPDF.md` | Cadeia de erros da quebra de colunas |
| `90-LEGADO/DIARIO_OFICIAL_ALTERACOES.md` | Alterações da passagem v5 → v6 |
| `90-LEGADO/ESTRUTURA_DIARIO_ATUAL.md` | Estrutura consolidada do diário |
| `90-LEGADO/2026-09-11-diario-upgrade-backlog.md` | Backlog de evolução v5 → v6 |

> **Atenção:** parte do legado reflete o estado **v5** (rotas antigas, sufixos
> `_two` de views, `summernote-diario.js`, 5 sub-serviços de PDF). Onde há
> divergência, este dossiê manda: o **v6 verificado no código** é a referência.

## 11. Riscos de topo (resumo)

| # | Risco | Severidade |
|---|-------|:----------:|
| 1 | Senha do certificado escrita em log e passada a `shell_exec` sem escape | alta |
| 2 | `generation_status = 'pending'` sem job/command que consuma (diário fica "Gerando PDF" indefinidamente no portal) | alta |
| 3 | QR Code gravado sempre em `public/img/qrcode.png` (concorrência sobrescreve) | média |
| 4 | Duplicação na tabela `modulos`: id 16 (`diario-ofifical`, typo) e id 37 (`diario-oficial`) | média |
| 5 | Permissão de subárea resolvida como `diario-area` no DataTable | média |
| 6 | Geração de PDF síncrona no request, sem fila, com `@set_time_limit(0)` | média |

Detalhamento em `08-GAPS-E-DIVIDAS.md`.
