# Unidade Gestora — Resumo Executivo

> **Versão analisada:** `v6` (o módulo é **idêntico** na `v5` — arquivos byte-a-byte iguais)
> **Slug do módulo:** `unidade-gestora` (tabela `modulos`) — id `50`, nome "Unidades Gestoras"
> **Natureza:** CMS (painel administrativo)
> **Estado:** OK v6 (migrado v5 -> v6 sem alterações de código)

---

## 1. Objetivo

O módulo cadastra e mantém a **relação de unidades gestoras** da prefeitura: as
órgãos/entidades responsáveis por uma licitação. Uma unidade gestora é uma entidade
simples, com **nome** e **código**, e é usada como chave de agrupamento no módulo de
Licitações (`biddings.management_units_id`).

Serve ao operador do CMS que precisa classificar cada licitação sob o órgão
responsável, e serve como fonte de um `select` obrigatório no formulário de
licitação.

## 2. Efeito / Impacto

| Faixa | Efeito |
|---|---|
| Cidadão | Não há impacto direto: o módulo não tem página pública. O efeito é indireto, pela melhor classificação das licitações exibidas no portal. |
| Prefeitura (CMS) | Permite cadastrar, editar, listar, exportar e excluir (inclusive em lote) as unidades gestoras. |
| Transparência e legalidade | A unidade gestora é o **responsável legal** pela licitação. Sem ela, a licitação não pode ser registrada (`management_units_id` é `NOT NULL`). |
| Operação técnica | O módulo está **desabilitado** no menu do CMS (`modulos.status = false`) e as telas continuam acessíveis por URL direta. |

## 3. Comportamento

- **Listagem** (`/cms/unidade-gestora`): DataTable server-side alimentado pela view
  SQL `unidade_gestora`, com colunas "ID", "Nome" e "Ações"; ordenação por nome
  (`ASC`).
- **Exclusão em lote**: o operador marca N linhas e aciona
  `POST /cms/ajax/unidade-gestora/delete-por-lote`; a resposta é JSON
  (`true`/`false`) e a tela recarrega a tabela.
- **Exclusão individual**: `DELETE /cms/unidade-gestora/{id}` devolve
  `{"success": "Unidade Gestora deletada com sucesso."}` com HTTP 200, ou
  `{"erro": "Ocorreu um erro ao tentar salvar no banco de dados."}` (PDOException) ou
  `{"erro": "Ocorreu um erro! Por favor entre em contato com o suporte técnico."}`
  (Exception genérica) com HTTP 500.
- **Exclusão é lógica** (`SoftDeletes`): a linha recebe `deleted_at` e some da
  listagem (a view SQL filtra `deleted_at IS NULL`).
- **Validação de unicidade**: `name` e `code` são `unique` em `management_units`
  **apenas na criação**. Na atualização, a regra aplicada é
  `unique:persons,cpf,{id}` — **tabela e coluna erradas** (bug U1).
- **Limites**: `name` e `code` são obrigatórios, com no máximo 120 caracteres
  (formulário e `ContentRequest`-equivalente do módulo).
- **Clique de menu**: ao abrir qualquer tela do módulo, o controller chama
  `menuClicks('licitacao')` — o contador de "Licitações" é incrementado, não o do
  módulo (bug U2).
- **Logs de atividade**: a exclusão em lote registra um log
  "Exclusão de uniade gestora" (grafia incorreta no texto, bug U3) com a lista de ids.

## 4. Como o Usuário Interage

1. Acessa `/cms/unidade-gestora` (AdminLTE). O cabeçalho mostra "Lista de Unidades Gestoras".
2. Botão **"Cadastrar Unidade Gestora"** (visível apenas com a permissão
   `unidade-gestora.create`) abre `/cms/unidade-gestora/create`.
3. Preenche **Código** e **Nome** (ambos obrigatórios, até 120 caracteres) e
   submete. Em caso de sucesso: flash "Unidade Gestora cadastrada com sucesso." e
   redirect para a listagem.
4. Na listagem, cada linha tem os botões **editar** (`/cms/unidade-gestora/{id}/edit`)
   e **excluir** (DELETE). Com a permissão `unidade-gestora.delete`, aparece também
   o botão **"Excluir Registro(s)"** (exclusão em lote), com contador de
   selecionados.
5. A tela oferece exportação **Excel, PDF, CSV e TXT** (botões do DataTable).
6. Ao criar/editar uma licitação, o operador escolhe a "Unidade Gestora" em um
   `select` obrigatório.

## 5. Detalhes e Particularidades Técnicas

- **Camadas:** `routes/basepro.php` -> `Prefecture\ManagementUnitController`
  (middleware `check.route.permission`) -> `ManagementUnitRequest` (Form Request)
  -> model `App\Prefecture\ManagementUnit` -> `management_units`.
- **Repository** `ManagementUnitRepositoryDefaultImpl` existe e é injetado no
  controller, mas **só é usado na exclusão em lote** (`destroyAll`). O
  `store`/`update` usam `ManagementUnit::create()/update()` diretamente.
- **Contrato vazio:** `IManagementUnitRepository` não declara nenhum método; toda a
  API vem da classe-base `App\Repositories\Repository`.
- **View SQL** `unidade_gestora` (criada em 2023) é a fonte da listagem do CMS; ela
  expõe `value` (numeração), `nome` e `id`.
- **Relacionamentos invertidos:** `ManagementUnit::biddings()` é `belongsTo` e
  `Bidding::managementUnits()` é `hasOne` — nenhum dos dois é o tipo correto
  (bug U4).
- **Dependências:** `spatie/laravel-activitylog` (log de exclusão),
  `yajra/laravel-datatables-oracle` (listagem), `laravelcollective/html` (formulários),
  `cartalyst/sentinel` (permissões e log do ator).

## 6. Estrutura de Dados

| Objeto | Natureza | Detalhe |
|---|---|---|
| `management_units` | tabela | `id` (PK), `name` (varchar 191, not null), `code` (varchar 191, not null), `created_at`, `updated_at`, `deleted_at` |
| `biddings.management_units_id` | FK | `integer NOT NULL` -> `management_units.id` |
| `unidade_gestora` | view SQL | `value`, `nome`, `id` (filtra `deleted_at IS NULL`) |
| `modulos` | tabela | `id = 50`, `slug = 'unidade-gestora'`, `name = 'Unidades Gestoras'`, `status = false` |
| `resources` | tabela | `id = 21`, `slug = 'unidade-gestora'`, `modulo_id = 50` (permissoes `unidade-gestora.*`) |
| `menu_orders` | tabela | **não existe** linha com `slug = 'unidade-gestora'` |

## 7. Como Testar

- Criar uma unidade com nome e código; confirmar o flash de sucesso e a presença na
  listagem.
- Tentar criar uma segunda unidade com o **mesmo** nome -> deve falhar
  ("O nome já está em uso.").
- Tentar criar com nome vazio -> "O campo nome é obrigatório.".
- Editar e confirmar a alteração.
- Excluir em lote (2 registros) -> JSON `true` e tabela recarregada sem as linhas.
- Confirmar no banco que `deleted_at` foi preenchido (exclusão lógica).
- Confirmar que a unidade continua selecionável no formulário de licitação
  (`biddings.management_units_id`).

## 8. Migração para Laravel Moderno

Model `ManagementUnit` com `$fillable = ['name', 'code']`, casts e
`SoftDeletes`; `FormRequest` com `unique:management_units,name,{id}` **corrigido**
(tabela e coluna corretas nos dois casos); `Policy` para
`unidade-gestora.{index,create,edit,delete}`; endpoint REST
`/api/admin/management-units` com `ApiResource`; `belongsTo`/`hasMany` corrigidos
em relação a `Bidding`; enum ou tabela de referência para `code` se a prefeitura
quiser padronizar a codificação; e um índice unique **parcial** (ignorando
`deleted_at`) em `name` e `code` no PostgreSQL.

## 9. Resumo Geral

O módulo "Unidades Gestoras" é um CRUD mínimo: nome e código, com listagem em
DataTable sobre a view SQL `unidade_gestora`, exclusão lógica individual e em lote,
e permissões `unidade-gestora.*`. Seu valor funcional está em ser a chave
`biddings.management_units_id` (NOT NULL) que identifica o órgão responsável por
cada licitação. O código é idêntico entre v5 e v6 — nenhuma migração de lógica
ocorreu. Os riscos estão concentrados em bugs reais e verificáveis: a regra de
unicidade da atualização aponta para a tabela `persons` e a coluna `cpf`; o
contador de cliques de menu grava em "licitacao"; a rota `show` gerada pelo
`Route::resource` não tem método correspondente no controller; a view `show.blade.php`
usa uma variável (`$functionality`) que o controller nunca envia; e as relações
Eloquent entre `ManagementUnit` e `Bidding` estão invertidas. Na reconstrução, a
correção da unicidade e das relações, mais a policy e a API, são o caminho curto.

---

## Í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 |
