# Arquivo (Drive) — Gaps, Dívidas e Regressão v5 -> v6

> **Módulo com implementação parcial na v6.** A tabela `archives`, o
> `ArchiveController` e as rotas do galeria **existem na v6**; a
> **categorização de arquivos** (tabela, model, controller, rotas e UI)
> **existe apenas na v5**.

---

## 1. Bugs e erros conhecidos

| # | Sev. | Descrição | Evidência |
|---|---|---|---|
| B01 | **Crítica** | **Rotas do Drive sem autenticação nem autorização.** `ArchiveController` e `ArchiveCategoryController` sobrescrevem `__construct()` sem chamar `parent::__construct()`, que é quem registra `check.route.permission` (`v5/app/Http/Controllers/Prefecture/Controller.php:19-23`). Resultado: `GET /cms/drive/categorias` responde **200** com o JSON das categorias e `POST /cms/drive/cadastrar/categoria` **cria uma categoria** sem qualquer sessão. Verificado em execução. | `v5/app/Http/Controllers/Prefecture/ArchiveController.php:38-41`; `v5/app/Http/Controllers/Prefecture/ArchiveCategoryController.php:16-19`; `php artisan route:list` mostra apenas `web` nas rotas do Drive; `curl` sem cookie → 200 |
| B02 | **Crítica** | O mesmo bug existe na **v6** (`v6/app/Http/Controllers/Prefecture/ArchiveController.php:33-37`), que também sobrescreve o construtor. As rotas `cms/galeria/*` e `cms/galeria/update-*` respondem sem sessão. | idem, `v6/routes/basepro.php:385-389` |
| B03 | Alta | **`updateOrder` reordena sem escopo.** Troca o `order` entre **qualquer** par de arquivos, inclusive de contextos diferentes (Drive ↔ conteúdo ↔ galeria de página). Um item do Drive pode tomar a posição 1 de um conteúdo. | `v5/app/Http/Controllers/Prefecture/ArchiveController.php:199-240` (`DB::table('archives')->where('id', …)`) |
| B04 | Alta | **`updateOrder` ignora `SoftDeletes`** (usa `DB::table`), permitindo reordenar e consultar arquivos já excluídos. | idem |
| B05 | Alta | **`dd($exception)` no tratamento de erro do upload** interrompe a requisição e entrega um **stack trace em HTML** ao cliente, em vez do JSON de erro previsto logo abaixo (o `return` é inalcançável). | `v5/app/Http/Controllers/Prefecture/ArchiveController.php:150-156` |
| B06 | Alta | **`category_id` não é validado** no upload → violação da FK `archives_category_id_foreign` → exceção não capturada (mesma armadilha de B05). | `ArchiveController.php:134` e migration `2025_10_16_105256` |
| B07 | Alta | **Categoria duplicada** → violação de `archive_categories_slug_unique` → `QueryException` não capturada → **500 com stack trace**. Verificado em execução. | `v5/app/Http/Controllers/Prefecture/ArchiveCategoryController.php:27-40` |
| B08 | Média | **`slug_fix()` não gera slug canônico**: apaga o hífen e **preserva a caixa**. Verificado: `"TESTE-PROBE"` → `"TESTEPROBE"`, `"Relatórios"` → `"Relatorios"` (≠ `relatorios` do seed). Categorias duplicadas com nomes iguais escapam da constraint. | `v5/app/Helpers/functions.php:771-778` |
| B09 | Média | **Duplicidade de nome sobrescreve o arquivo em disco.** `fileExistsInPath()` usa `file_exist("storage/{$dir}/{$nameFile}")` — caminho **relativo** que quase nunca resolve a partir do `public/` — logo a proteção é inócua e dois uploads com o mesmo `nameFile` sobrescrevem o binário, deixando duas linhas apontando para o mesmo `path`. | `v5/app/Http/Traits/FileTrait.php:84-87` e `:52-58` |
| B10 | Média | **`hash` nunca corresponde ao arquivo servido**: é o `md5_file()` do temporário, mas `compress()` reescreve o binário depois. A coluna não é consultada em lugar nenhum. | `ArchiveController.php:137` vs. `FileTrait::compress()` |
| B11 | Média | **`path` com formatos heterogêneos** — `storage/…`, URL absoluta (`http://host/storage/answer/…`), `docs/…`, e até sem o prefixo `storage` (`ArchiveRepository::upInsert` faz `str_replace`). O portal usa `file_exist($archive->path)` e `url($archive->path)`, que **quebram** para URL absoluta e para caminho relativo ao CWD. | `02-MODELAGEM.md` §1.4 |
| B12 | Média | **`order` fora do `$fillable`** do model v5 → `Archive::create(['order' => …])` é silenciosamente ignorado. | `v5/app/Http/Model/Prefecture/Archive.php:19-40` |
| B13 | Média | **`getArchivesFromGalleryOrDriver` aceita o nome da coluna pela URL** (`{column?}` → `->where($colunm, $id)`). Não há SQL injection (o grammar 5.5 envolve o identificador em aspas — verificado), mas é **enumeração de colunas** por um endpoint sem autenticação. | `ArchiveController.php:167-183`; verificação: `where('id) or 1=1 --', 1)` → `"id) or 1=1 --" = ?` |
| B14 | Média | **Relações quebradas no model**: `Archive::contests()` aponta para o pivot inexistente `contests_has_archives` (QueryException) e `Archive::biddings()` usa a coluna inexistente `bidding_id` (o correto é `biddings_id`). `Contest::archives()` aponta para `static_pages_has_archive`, também inexistente. Verificado em execução. | `v5/app/Http/Model/Prefecture/Archive.php:64-73`; `v5/app/Http/Model/Prefecture/Contest.php:32` |
| B15 | Média | **`Archive::biddingModalities()`** gera SQL autocontraditório (`"bidding_modalities"."id" is null and ... is not null`) — retorna sempre vazio. | `v5/app/Http/Model/Prefecture/Archive.php:88-91` |
| B16 | Média | **`ArchiveCategory` sem `SoftDeletes`**, apesar de a tabela ter `deleted_at`; o filtro é manual (`where('deleted_at', null)`) e **não existe rota de exclusão** → a coluna nunca é preenchida e o `ON DELETE SET NULL` nunca é exercitado. | `v5/app/Http/Model/Prefecture/ArchiveCategory.php` |
| B17 | Média | **`getCategories()` devolve a collection completa** sem paginação nem cache. | `ArchiveCategoryController.php:20-25` |
| B18 | Média | **O Drive não pagina no servidor**: o endpoint devolve **todos** os arquivos de uma vez e o JS fatia em lotes de 50 no cliente, disparando **um `HEAD` HTTP por arquivo** (50 requisições por rolagem). | `v5/public/assets/js/custom/contents/midias/index.js:194-242` |
| B19 | Média | **A exclusão não apaga o binário**: o arquivo continua acessível por `GET /storage/…` mesmo após o soft delete. | `ArchiveController@deleteArchives` (só `destroy()`) |
| B20 | Média | **`nameFile` do usuário não é sanitizado** — é concatenado à extensão e usado direto no `storeAs`. O Laravel 5.5 normaliza o path com `trim($path.'/'.$name, '/')` mas **não resolve `..`**. | `ArchiveController.php:122-124`; `v5/vendor/laravel/framework/src/Illuminate/Filesystem/FilesystemAdapter.php:205-221` |
| B21 | Média | **Não há validação de upload** no controller: sem `max:`, sem lista de MIME, sem verificação da extensão real. Só existe o `acceptFiles` do plugin JS (que é contornável). | `ArchiveController@saveArchivesFromGalleryOrDriver` |
| B22 | Média | **`order` NULL** quebra a ordenação: `null == null` é verdadeiro, então a "correção de ordem duplicada" dispara para arquivos sem ordenação e `null + 1 = 1` — todos os arquivos sem ordem caem na posição 1. | `ArchiveController.php:216-219` |
| B23 | Baixa | **Agrupamento de rotas com nomes colididos**: as 3 rotas do grupo `galeria` recebem o nome herdado `galeria.` (o prefixo `as` do grupo só é aplicado a rotas que chamam `->name()`), impossibilitando `route()` e gerou **3 rotas com o mesmo nome**. | `v5/routes/basepro.php:381-385`; `php artisan route:list` |
| B24 | Baixa | **Código morto**: `v5/public/assets/js/custom/utilities/helpers/sortable-galerias.js` (único chamador de `POST /order` e `PUT /order`) **não é incluído por nenhuma view** — as rotas `/order` não têm consumidor. | `grep -rn "sortable-galerias" v5/resources/views/` → vazio |
| B25 | Baixa | **`delete_archive.js`** redireciona para `/deletar-arquivo-padrao` — que é a rota do **Requerimento de Diárias**, não do módulo de arquivo. O nome do arquivo é enganoso. | `v5/public/assets/js/custom/utilities/helpers/delete_archive.js`; `v5/routes/basepro.php:567` |
| B26 | Baixa | **A lista de categorias no modal não é recarregada** após criar uma: `categories.push(formValues)` insere uma **string** no array, e o `map` seguinte espera objetos (`c.name`) → o item exibido fica vazio. | `v5/public/assets/js/custom/contents/midias/index.js:394-400` |
| B27 | Baixa | **`myFetch` retorna `undefined` em erro de rede** (o `catch` não tem `return`), e o chamador faz `result.success` → `TypeError` em vez de mensagem ao usuário. | `v5/public/assets/js/custom/utilities/functions.js:85-88` |
| B28 | Baixa | **A busca do Drive é client-side** e filtra por nome **ou** categoria; não há indicação de "0 resultados" nem de total. | `v5/public/assets/js/custom/contents/midias/index.js:327-336` |
| B29 | Baixa | **A exclusão recarrega a página** em `archives-pages.js` (`location.reload()`), descartando o estado da galeria. | `v5/public/assets/js/custom/contents/paginas-estaticas/archives-pages.js:12` |
| B30 | Baixa | **`emendas_has_archives` não tem chave primária** nem timestamps → duplicatas silenciosas dependem do plano de execução. | `v5/database/migrations/2026_03_13_103000_create_emendas_has_archives_table.php` |
| B31 | Baixa | **Colunas mortas**: `status_create` (nunca escrita em todo o código v5) e `biddings_id` (FK direta substituída pelo pivot; 0 linhas). | `02-MODELAGEM.md` §1.1 |
| B32 | Baixa | **Confusão de nomes**: `highlight` (boolean, "é a imagem de destaque") e `highlight_id` (FK para o módulo de banners) coexistem na mesma tabela. | migration `2025_03_31_210313_create_highlights_table.php` |
| B33 | Baixa | **`work_archives.type` é `varchar` sem CHECK** — um valor fora de `gallery`/`file` quebra o filtro do `WorkController`. | `v5/database/migrations/2025_04_01_021111_create_work_archives_table.php` |
| B34 | Baixa | **`IArchiveRepository` é uma interface vazia** — não há contrato a respeitar nem a testar. | `v5/app/Repositories/Contracts/IArchiveRepository.php` |
| B35 | Baixa | **`ArchiveRepository::upInsert()` grava a linha e o arquivo fora da mesma transação** → falha no upload deixa linha órfã. Também **não é usado** por nenhum controller do módulo. | `v5/app/Repositories/Eloquent/Prefecture/Archive/ArchiveRepository.php` |
| B36 | Baixa | **A ordenação do Drive depende do `jquery-ui.js`** que não é incluído pelo `form.blade.php` (apenas o CSS da CDN). O JS existe em `v5/public/assets/plugins/jquery-ui/jquery-ui.min.js` e precisa estar no layout. | `v5/resources/views/prefecture/contents/midias/form.blade.php:4` |

## 2. Funcionalidades incompletas ou mortas

| # | Item | Situação |
|---|---|---|
| M01 | **Categorização incompleta** | Só existe `getCategories` e `store`. **Não há** editar, renomear, reordenar nem excluir categoria. Uma categoria errada é **irreversível** pela aplicação. |
| M02 | **Filtro por categoria no servidor inexistente** | A categorização só existe no Drive; a listagem por escopo (`/cms/galeria/{col}/{id}`) **não** aceita `category_id`. O filtro no front é client-side. |
| M03 | **A categoria não aparece no portal** | Nenhuma view do portal exibe a categoria do arquivo — o cidadão não sabe a que pasta o documento pertence. |
| M04 | **A ordenação por `order` só vale para o Drive** | `defaultOrder`/`reorder` recebem `contents_id` — a ordenação de galeria de **página estática** ou **evento** não tem endpoint equivalente (e o JS chamador está morto, B24). |
| M05 | **`order` inconsistente** | Só o bucket "midias" recebe `order = id` no upload; as demais galerias ficam com `order = NULL`. `ExtrasSeeder` só normaliza `%midias%`. |
| M06 | **Sem "usar arquivo do Drive" no seletor de conteúdo** | O Drive é uma galeria; **não há** um seletor que permita reaproveitar uma mídia já existente em outro conteúdo. Cada upload cria uma nova linha. |
| M07 | **Sem auditoria de exclusão** | `deleteArchives` não chama `activity()`; a remoção de um documento não fica registrada. |
| M08 | **Sem autoria** | `archives` não tem `created_by`/`updated_by`. Só o `activity_log` registra quem cadastrou, e só em parte dos fluxos. |
| M09 | **Sem auditoria de reordenação** | Trocar a ordem de documentos não é registrado. |
| M10 | **Sem limpeza de órfãos** | Não há job para remover binários de arquivos deletados ou de linhas removidas. |
| M11 | **Sem verificação de integridade** | `hash` não é usado; não há detecção de arquivo corrompido nem deduplicação. |
| M12 | **Sem metadados** | Sem EXIF, sem data de originals, sem checksum do servidor. |
| M13 | **Sem varredura de segurança** | Não há antivírus, nem verificação de tipo real do arquivo (só o MIME declarado). |
| M14 | **Sem rótulo/marca d'água** | Sem opcional de marca d'água em documentos. |
| M15 | **Sem estatísticas** | Não há relatório de "arquivos mais baixados" nem de espaço ocupado. |
| M16 | **Coluna `status_create` morta** | Criada em 2018 e nunca usada. |
| M17 | **Coluna `biddings_id` morta** | FK direta substituída pelo pivot `biddings_has_archives`; 0 linhas preenchidas. |
| M18 | **`Archive::contests()` e `Archive::biddings()` mortas** | Nenhuma consulta no código usa essas relações; ambas estão quebradas (B14). |
| M19 | **Coluna `reference_id` sem integridade** | `text` usada como FK por `PaginasSecretaria`; sem índice e sem constraint. |
| M20 | **Acervo vazio na base analisada** | Os 91 registros de `archives` são **exclusivamente** as imagens do manual do sistema. O Drive real nunca foi alimentado neste ambiente; `order` e `category_id` estão 100% vazios. |

## 3. Riscos de dados (migração de schema)

| # | Risco | Impacto | Mitigação |
|---|---|---|---|
| D01 | **Colunas polimórficas → coluna única** | Migrar 7 `*_id` para `attachable_type`/`attachable_id` perde as FKs reais (licitações, diárias, banners) | Manter as FKs em tabelas pivot dedicadas ou aceitar FKs lógicas com validação em código |
| D02 | **`path` multi-formato** | Renomear/mover os binários sem reescrever o `path` deixa links publicados quebrados | Job idempotente de normalização + relatório de `path` irreconhecíveis (MIG03/MIG04 em `07-TESTES.md`) |
| D03 | **`highlight` tri-estado** | `true`/`NULL`/`false` → `is_featured` boolean perde o estado `false` | Migrar `NULL` → `false` e documentar a mudança de semântica do estado `false` |
| D04 | **`order` parcial e NULL** | Reindexar tudo pode alterar a ordem exibida de galerias já publicadas | Reindexar por escopo preservando a ordem relativa atual (`id ASC` como desempate) |
| D05 | **Ausência de índices** | `contents_id`, `static_pages_id`, `order`, `category_id`, `path` sem índice → varredura sequencial em tabelas grandes | Criar índice composto `(attachable_type, attachable_id, position)` |
| D06 | **`archives_biddings_legacy` órfã** | Tabela sem FK para `archives`, com colunas `name`/`biddings_legacys_id` — não é Clearly parte do modelo de arquivos | Confirmar com o negócio se é legada de fato; se sim, arquivar |
| D07 | **Duplicação de conceito**: `requerimento_diarias_configs.archive/path` (varchar) x `archives` | O "documento padrão" de diárias não passa por `archives` | Unificar no modelo novo ou manter a exceção documentada |
| D08 | **Coluna `hash` md5** | md5 não é seguro para integridade (colisão) | Trocar por sha256 se o hash for mantido |
| D09 | **Soft delete sem limpeza** | O storage cresce sem limite e documentos "removidos" continuam públicos | Job `DeleteArchiveFile` com janela de graça |
| D10 | **Ausência de `created_by`** | Impossibilidade de auditar quem publicou um documento | Adicionar `user_id` (nullable) + migration de backfill |
| D11 | **Datas com `timestamp(0)`** | Precisão de segundos; sem timezone explícito | `timestampTz` na v7 |

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

1. A **categorização de arquivos** deve ser resgatada na v7? Se sim, 1:N
   (como a v5) ou N:N (um arquivo em várias pastas)?
2. As categorias devem aparecer para o **cidadão** no portal, ou são
   apenas uma ferramenta interna do operador?
3. A **exclusão** de um arquivo deve apagar o binário? O que acontece com
   os links `/storage/…` já publicados e indexados por buscadores?
4. O **Drive** deve permitir **reaproveitar** uma mídia já existente em
   outros conteúdos (em vez de upload repetido)?
5. Deve existir **limite de tamanho** por tipo de arquivo e por perfil de
   usuário? O front já anuncia "máximo de 128 MB".
6. É preciso **controle de versão** de um documento (ex.: uma certidão
   atualizada)?
7. Quais **perfis** podem excluir arquivos? Na v5 a rota nem exige login.
8. A ordenação é **por galeria** ou **global**? A v5 mistura as duas
   mecânicas (`/order` por `contents_id` e `/cms/drive/atualizar-ordem`
   global).
9. Deve haver **cota de espaço** por município?
10. Os **91 arquivos do manual do sistema** devem ser migrados para a v7 ou
    recriados como seed?

---

## 5. Regressão v5 -> v6

### 5.1 Panorama

| Aspecto | v5 | v6 | Situação |
|---|---|---|---|
| Tabela `archives` | ✅ 26 colunas | ✅ 26 colunas (−`category_id`, +`tv_camara_id`) | **Mantida, com troca de coluna** |
| Tabela `archive_categories` | ✅ 5 colunas | ❌ **não existe** | **REMOVIDA** |
| Coluna `archives.category_id` | ✅ FK SET NULL | ❌ | **REMOVIDA** |
| `Archive` (model) | ✅ | ✅ (sem `works()`, sem `category()`) | **Mantido, amputado** |
| `ArchiveCategory` (model) | ✅ | ❌ | **REMOVIDO** |
| `ArchiveController` | ✅ | ✅ (+2 métodos) | **Mantido e ampliado** |
| `ArchiveCategoryController` | ✅ | ❌ | **REMOVIDO** |
| Rotas `/cms/drive/*` | 3 | 0 | **REMOVIDAS** |
| Rotas `/cms/galeria/*` | 3 | 5 | **Mantidas e ampliadas** |
| Rotas `/order` | 2 | 2 | **Mantidas** |
| JS do Drive | com categoria + cropper | sem categoria + sem cropper | **REGRESSÃO** |
| Componente `archive.blade.php` | simples | com Sortable + edição inline | **Evoluiu** |
| `work_archives` (pivot) | ✅ | ❌ (sem módulo "obras") | **REMOVIDO** |
| `ombudsman_answer_archives` | ✅ | ❌ (migration ausente) | **REMOVIDO** |
| `emendas_has_archives` | ✅ | ✅ | **Mantido** |
| `biddings_has_archives` / `answer_archives` / `contract_archives` | ✅ | ✅ | **Mantidos** |
| `tv_camara_id` | ❌ | ✅ | **NOVO** |

### 5.2 Funcionalidade perdida

1. **Categorização de arquivos — removida por completo.** A tabela
   `archive_categories`, a coluna `archives.category_id`, o model
   `ArchiveCategory`, o controller `ArchiveCategoryController` e as três
   rotas `/cms/drive/categorias`, `/cms/drive/cadastrar/categoria` e
   `/cms/drive/atualizar-ordem` **não existem na v6**. O botão "Adicionar
   Categoria" sumiu do formulário do Drive, o seletor `<select
   id="swal-category">` sumiu do modal de upload e a coluna
   `image-category-box` sumiu do item da galeria.

2. **Editor de imagem no upload — removido.** A v5 abria o **CropperJS**
   (rotate/zoom) antes do envio; a v6 removeu o include de
   `prefecture.contents.components.editor-de-imagem.index`, o
   `cropper-min.js` e o `editor-de-imagem.js`
   (`diff v5/resources/views/prefecture/contents/midias/form.blade.php
   v6/resources/views/prefecture/contents/midias/form.blade.php`).

3. **Upload avançado — removido.** O `setupUpload()` da v5 (≈65 linhas:
   nome + categoria obrigatórios, tipos de arquivo ampliados — PDF, DOC,
   DOCX) foi substituído pela v6 por um `uploadFile()` simples de
   **apenas imagem** (`acceptFiles: "image/jpeg, image/png, image/jpg"`).
   Na prática, **a v6 não aceita mais PDF/DOC no Drive**.

4. **Ordenação do Drive — removida.** A v6 perdeu a rota
   `POST /cms/drive/atualizar-ordem` (a troca de `order` entre dois
   itens arrastados). Em contrapartida, ganhou
   `POST /cms/galeria/update-order`, que reordena **em lote** e — ao
   contrário da v5 — **escopa** por `related_type`/`related_id`
   (corrigindo o bug B03 da v5). A troca de ordem do Drive como operação
   independente **não existe mais**.

5. **Ordenação por `order` na listagem — removida.** Na v5,
   `getArchivesFromGalleryOrDriver` ordenava por `order DESC, id DESC`;
   na v6, apenas por `id DESC`. A coluna `order` continua no banco e
   passou a ser gerenciada só pela rota nova.

6. **Filtro por `path LIKE '%midias%'` — removido.** Na v6, a listagem
   sem `id` devolve **todos** os arquivos da tabela
   (`->orderBy('id','DESC')`), sem filtro de escopo. Isso é uma
   **regressão funcional**: o "Drive" da v6 lista o acervo inteiro.

7. **`with('category')` na listagem — removido** (naturalmente, já que a
   categoria não existe mais).

8. **Relação `Archive::works()` — removida** (o módulo "obras" não existe
   na v6; nem há `v6/app/Http/Model/Prefecture/Works/`).

9. **Pivot `work_archives` — removido** (migration
   `2025_04_01_021111_create_work_archives_table.php` ausente na v6).

10. **Pivot `ombudsman_answer_archives` — removido** (migration
    `2026_08_06_162636_create_ombudsman_answer_archives_table.php` ausente
    na v6), embora o model `OmbudsmanAnswer` da v6 **continue declarando**
    a relação `belongsToMany(Archive::class, 'ombudsman_answer_archives', …)`:
    a relação está órfã e quebra em tempo de execução.

11. **Recurso/módulo do CMS — renomeado.** Na v5 o recurso é
    `resources.id = 44`, `slug = midias`, `name = Drive`; na v6 é
    `resources.id = 34`, `slug = drive`, `name = Drive`, ligado ao
    `modulos.id = 30` (`slug = drive`). O item de menu da v5
    (`v5/app/Providers/MenuServiceProvider.php:283-285`, `case 'midias':`)
    foi substituído pelo item do `modulos` na v6.

### 5.3 Funcionalidade ganha na v6

| Ganho | Detalhe |
|---|---|
| `PUT /cms/galeria/update-title/{id}` | Edição **inline** de título/descrição do arquivo (`updateArchiveTitle`), com botão "Editar nome" no componente `archive.blade.php` e `toastr` de confirmação. |
| `POST /cms/galeria/update-order` | Reordenação **em lote** e **escopada** (`related_type`/`related_id`) — resolve o bug B03 da v5. |
| `archives.tv_camara_id` | FK para `tv_camaras` ON DELETE CASCADE (módulo TV Câmara, novo na v6). |
| `'order'` no `$fillable` | A v5 **não** tinha `'order'` no `$fillable` (bug B12); a v6 adicionou. |
| `'tv_camara_id'` no `$fillable` | — |
| Componente `archive.blade.php` com Sortable | Reordenação por arraste na listagem de anexos dos formulários, com `Sortable.create()` (Sortable.js 1.15) em vez do jQuery UI. |
| CSS dedicado | `v6/public/assets/css/custom/archive-sortable.css` (inexistente na v5). |
| Exclusão de **descrição** no componente | O `v6` mostra a descrição como campo editável (`file-description-display` / `file-description-input`). |

### 5.4 Mapa de rotas

| Rota | v5 | v6 |
|---|---|---|
| `POST /cms/galeria` | ✅ `saveArchivesFromGalleryOrDriver` | ✅ idem (**sem categoria**, sem nome customizado) |
| `GET /cms/galeria/{column?}/{id?}` | ✅ (`order DESC`, filtro `%midias%`, `with('category')`) | ✅ (**só `id DESC`**, **sem filtro de escopo**, **sem `with('category')`**) |
| `POST /cms/galeria/delete/{id}` | ✅ | ✅ idem |
| `PUT /cms/galeria/update-title/{id}` | ❌ | ✅ **novo** |
| `POST /cms/galeria/update-order` | ❌ | ✅ **novo** |
| `GET /cms/drive/categorias` | ✅ | ❌ **removida** |
| `POST /cms/drive/cadastrar/categoria` | ✅ | ❌ **removida** |
| `POST /cms/drive/atualizar-ordem` | ✅ | ❌ **removida** |
| `POST /order` | ✅ `defaultOrder` | ✅ idem |
| `PUT /order` | ✅ `putOrder` | ✅ idem |
| `DELETE /cms/secretarias_paginas/arquivo/{id}` | ✅ | ✅ idem |
| `POST /cms/galerias-obras` | ✅ | ❌ **removida** (módulo "obras" não existe na v6) |
| `GET /cms/galerias-obras/{id}` | ✅ | ❌ **removida** |

### 5.5 Mapa de migrations

| Migration | v5 | v6 | Efeito na v6 |
|---|---|---|---|
| `2018_04_02_181807_create_archives_table.php` | ✅ | ✅ | **Idêntica** (`diff` vazio) |
| `2022_01_07_111645_add_calendar_event_id_to_archives.php` | ✅ | ✅ | idem |
| `2022_04_12_124253_add_column_to_archives_table.php` | ✅ | ✅ | idem |
| `2022_11_29_092240_add_viewpdf_to_archives_table.php` | ✅ | ✅ | idem |
| `2023_02_01_083626_add_itens_to_archives.php` | ✅ | ✅ | idem (seed do manual) |
| `2023_03_31_142413_add_collum_reference_id_to_archives.php` | ✅ | ✅ | idem |
| `2023_07_24_130504_add_column_type_size_id_to_archives.php` | ✅ | ✅ | idem |
| `2023_08_03_100129_add_width_and_height_to_archives.php` | ✅ | ✅ | idem (`diff` vazio) |
| `2023_09_19_164831_add_requerimento_id_to_archives.php` | ✅ | ✅ | idem |
| `2024_11_16_121841_add_tv_camaras_id_in_archives.php` | ❌ | ✅ | **NOVA** — `tv_camara_id` |
| `2025_03_31_210313_create_highlights_table.php` | ✅ | ✅ | idem (cria `highlights` + `archives.highlight_id`) |
| **`2025_10_16_105153_create_archive_categories_table.php`** | ✅ | ❌ | **REMOVIDA** |
| **`2025_10_16_105256_add_category_into_archives.php`** | ✅ | ❌ | **REMOVIDA** (`archives.category_id`) |
| `2025_04_01_021111_create_work_archives_table.php` | ✅ | ❌ | **REMOVIDA** |
| `2026_08_06_162636_create_ombudsman_answer_archives_table.php` | ✅ | ❌ | **REMOVIDA** |
| `2026_03_13_103000_create_emendas_has_archives_table.php` | ✅ | ✅ | idem |

> Verificado no banco da v6 (`docker exec v6_6f22e1bd-postgres-1 psql`):
> a tabela `archives` da v6 tem **26 colunas** — as 26 da v5 **menos**
> `category_id` **mais** `tv_camara_id`. **Não existe**
> `archive_categories` nem `work_archives` nem
> `ombudsman_answer_archives`; existem `answer_archives`,
> `contract_archives` e `emendas_has_archives`.

### 5.6 Mapa de models

| Model | v5 | v6 | Diferença |
|---|---|---|---|
| `App\Prefecture\Archive` | ✅ | ✅ | v6 **remove** `use App\Prefecture\Works\WorkArchive;`, o método `works()` e o método `category()`; **adiciona** `'tv_camara_id'` e `'order'` ao `$fillable` e **remove** `'category_id'`. |
| `App\Prefecture\ArchiveCategory` | ✅ | ❌ | **REMOVIDO** |
| `App\Prefecture\Works\WorkArchive` | ✅ | ❌ | **REMOVIDO** |
| `App\Prefecture\BiddingHasArchive` | ✅ | ✅ | idem |
| `App\Prefecture\Answer` | ✅ | ✅ | idem |
| `App\Prefecture\OmbudsmanAnswer` | ✅ | ✅ | idem — mas o pivot `ombudsman_answer_archives` **não existe** na v6 (relação órfã) |
| `App\Prefecture\Contract` | ✅ | ✅ | idem |
| `App\Prefecture\EmendaParlamentar` | ✅ | ✅ | idem |
| `App\Prefecture\Content` | ✅ | ✅ | idem |
| `App\Prefecture\Highlight` | ✅ | ✅ | idem |
| `App\Prefecture\Diario` / `DiarioConfig` | ✅ | ✅ | idem |

### 5.7 Mapa de assets

| Asset | v5 | v6 | Diferença |
|---|---|---|---|
| `public/assets/js/custom/contents/midias/index.js` | ✅ | ✅ | v6 **remove** ~65 linhas (fluxo de categoria, modal de nome, tipos de arquivo ampliados). |
| `public/assets/js/custom/utilities/helpers/add_archive.js` | ✅ | ✅ | **Idêntico** (`diff` vazio). |
| `public/assets/js/custom/utilities/helpers/delete_archive.js` | ✅ | ✅ | **Idêntico**. |
| `public/assets/js/custom/contents/paginas-estaticas/archives-pages.js` | ✅ | ✅ | Presente nos dois. |
| `public/assets/js/custom/utilities/helpers/sortable-galerias.js` | ✅ (morto) | ✅ (morto) | idem. |
| `public/assets/css/custom/archive-sortable.css` | ❌ | ✅ | **NOVO** na v6. |
| `resources/views/components/inputs/archive.blade.php` | ✅ | ✅ | v6 **reescreve** (Sortable.js + edição inline de descrição + `->sortBy('order')`). |
| `resources/views/prefecture/contents/midias/form.blade.php` | ✅ | ✅ | v6 **remove** botão de categoria, modal de edição, include do editor de imagem e o CSS do CropperJS. |
| `resources/views/prefecture/contents/midias/edit.blade.php` | ✅ | ✅ | idem. |

### 5.8 Impacto para a v7

A v6 **não é** um "superconjunto" da v5 neste módulo: ela **perdeu** a
categorização, o editor de imagem, o upload de documentos (PDF/DOC) no
Drive, a ordenação independente do Drive e o filtro de escopo do Drive —
e **ganhou** edição inline, reordenação em lote e escopada, e o campo
`tv_camara_id`.

Recomendação:

1. **Resgatar as categorias** (a perda mais relevante para a operação do
   CMS) — recriar `archive_categories` com a semântica 1:N da v5 e, se o
   negócio quiser, evoluir para N:N.
2. **Resgatar o upload de documentos** no Drive (o `acceptFiles` da v5
   permitia PDF/DOC/DOCX; o da v6 só permite imagem).
3. **Manter** a reordenação em lote e escopada da v6 (não voltar ao
   `updateOrder` da v5, que trocava a ordem entre contextos).
4. **Manter** a edição inline de título/descrição da v6.
5. **Corrigir B01/B02** (autorização) em qualquer uma das versões —
   é o item mais grave.
6. **Reavaliar** o `acceptFiles` e o cropper: o recorte de imagem é útil
   para o avatar/galeria, mas o fluxo da v5 era mais simples.
