# Licitações — Resumo Executivo

> **Versão analisada:** `v6` (módulo também existe na `v5`, com diferenças — ver `08-GAPS-E-DIVIDAS.md`)
> **Slug do módulo:** `licitacoes` (tabela `modulos`, id 21 — “Licitações”)
> **Recurso de permissão:** `licitacao` (tabela `resources`, id 20)
> **Natureza:** CMS (painel administrativo) + Portal (público)
> **Estado:** migrado v5 -> v6 (mesmo código, com ajustes de ordenação e remoções)

---

## 1. Objetivo

O módulo de Licitações publica e gerencia os processos licitatórios da Prefeitura:
cadastra cada licitação (número, processo, objeto, valor, modalidade, tipo, unidade
gestora, secretarias jurisdicionadas, situação, datas) e a torna pública no portal,
onde o cidadão consulta, filtra, abre o detalhe, acompanha as propostas
apresentadas e visualiza os contratos firmados. Sustenta a obrigação de
transparência e de publicidade dos certames (Lei 8.666/93 e, a partir de 2021,
Lei 14.133/21, reflected nas modalidades cadastradas).

## 2. Efeito / Impacto

| Faixa | Efeito |
|---|---|
| Cidadão | Lista pública de licitações com filtros (período, número, processo, modalidade, situação, órgão, local, faixa de valor, tipo de objeto, participante, show artístico), detalhe completo, download de edital e demais anexos, e exportação em xls/pdf/csv/txt. |
| Prefeitura (CMS) | Cadastro, edição e exclusão de licitações, tipos e modalidades; upload de arquivos do edital (edital, anexos, publicação); exclusão em lote; log de auditoria via `spatie/laravel-activitylog`. |
| Transparência e legalidade | Publicidade de cada certame, com identificação de valor estimado (controlada por `show_value`), situação, participantes e contratos. |
| Operação técnica | Tabela `biddings` é a fonte; a listagem do CMS lê a **view SQL `licitacao`**, não a tabela. |

## 3. Comportamento

- Uma licitação é identificada por `number` (máx. 15 caracteres) **combinado** com
  `bidding_modalities_id` e com o conjunto de secretarias “jurisdicionado”.
  A unicidade é verificada em código, no controller, e **não** por constraint no banco.
- A situation (`statuses_id`) só pode assumir os status da categoria 2
  (`status_category_id = 2`): **Aberta (5)**, **Finalizada (6)**, **Cancelada (7)**.
- `show_value` decide se o valor estimado é exibido no portal (`Indisponível` quando falso).
- `is_show` marca a licitação como “show artístico” e habilita o filtro “Apenas Shows”.
- A publicação do edital (`publication_edital_date`) e a data do certame
  (`competition_date`) são **opcionais** (a obrigatoriedade foi removida em 2019).
- A exclusão é bloqueada quando a licitação já tem propostas vinculadas
  (`proposals.biddings_id`); a exclusão em lote pula somente as que têm propostas.
- Arquivos são gravados em `storage/licitacao/{id}/arquivos/` e vinculados por
  `biddings_has_archives`.
- Contratos podem ser vinculados a uma proposta (`contracts.proposals_id`) **e**
  diretamente a uma licitação (`contracts.bidding_id`, FK adicionada em 2025-03-07).
- O portal ordena a listagem por `homologation_date` (nulos por último) e, em
  seguida, por `publication_edital_date` decrescente (regra alterada na v6).

## 4. Como o Usuário Interage

**Operador (CMS, `/cms`)**:

1. `Licitações` → lista em DataTable alimentada por `/cms/datatable/licitacao`
   (view SQL `licitacao`), com colunas ID, Número, Valor, Modalidade,
   Data de publicação, Tipo, Situação e ações.
2. `Cadastrar Licitação` → formulário com situação, número, unidade gestora,
   tipo de objeto, modalidade, local, secretarias jurisdicionadas (multi),
   data de publicação do edital, data/hora do certame, número do processo,
   objeto (summernote), data de homologação, “publicar valor estimado?”,
   valor e arquivos (descrição + upload).
3. `Editar` → mesmo formulário; arquivos já enviados aparecem com download /
   visualizar / deletar (deleção via `POST /cms/ajax-delete-files-licitacoes`).
4. Exclusão individual ou em lote (`POST /cms/licitacao/delete-por-lote`).
5. Submenus `Tipos de Licitação` (`/cms/tipo-licitacao`) e `Modalidades`
   (`/cms/modalidade-licitacao`) — CRUD simples, apenas `name`.

**Cidadão (portal)**:

1. `/licitacoes` → tabela com microdata (`schema.org` `Bidding`), botões
   “+” (expande as propostas na própria linha) e lupa (abre o detalhe).
2. `/licitacao/{id}` → detalhe: situação, número, unidade gestora, tipo,
   secretarias, modalidade, datas, objeto, valor, arquivos, propostas e contratos.
3. `/contratos` → listagem de contratos com filtros próprios;
   `/contrato/{contractId}` → detalhe do contrato.
4. Exportação: `xls`, `pdf` (server-side), `csv`, `txt` — via `GET /exportacao`.

## 5. Detalhes e Particularidades Técnicas

- Camadas: `Route` -> middleware (`check.route.permission` no CMS) -> Controller ->
  `BiddingRequest` -> `BiddingRepositoryDefaultImpl` -> Model `Bidding` -> PostgreSQL.
- O portal **não** usa o controller do CMS: há `Portal\BiddingsController` +
  `App\Http\Filter\FilterBiddings` para filtro e `Portal\ContractController` para contratos.
- A listagem do CMS usa a **view `licitacao`** (criada por
  `v6/database/migrations/2023_04_06_100010_create_view_to_licitacao.php`);
  o portal usa Eloquent sobre `biddings`.
- A rota `licitacao-ajax-detalhe/{id}` aponta para `ajaxShowDetail`, **método
  inexistente** em `Portal\BiddingsController` — rota morta (500 se acessada).
- `BiddingType::biddings()` aponta para a coluna `bidding_type_id`, que **não
  existe** (a coluna real é `bidding_types_id`) — relação quebrada.
- `BiddingRequest` mantém commented-out a regra `unique` de `number`; a unicidade
  é imposta no controller por consulta (número + modalidade + jurisdicionados).
- O CMS usa `is_show` com o rótulo **“Show Artístico”** (herança de outro módulo).

## 6. Estrutura de Dados

| Tabela / Objeto | Papel |
|---|---|
| `biddings` | Licitação (número, datas, objeto, valor, FKs de unidade/modalidade/tipo/situação, `local`, `is_show`). |
| `bidding_types` | Tipos de objeto (Alienação, Compras e Serviços, Obras e Serviços de Engenharia). |
| `bidding_modalities` | Modalidades (Lei 8.666/93, Lei 14.133/21, MP 1.047/21, internacionais, Credenciamento). |
| `biddings_has_archives` | Pivot `biddings_id` <-> `archives_id` (com soft delete). |
| `bidding_jurisdictionals` | Secretarias/órgãos jurisdicionados de cada licitação. |
| `archives` | Arquivo (edital/anexo) com `path`, `name`, `title`, `extension`, `type`. |
| `contracts` | Contrato (número, datas, valor, `proposals_id`, `bidding_id`). |
| `proposals` | Proposta de um proponente para uma licitação (`winner`, `value`). |
| view `licitacao` | Projeção para o DataTable do CMS (número, valor, modalidade, data, tipo, situação, id + `row_number`). |
| `statuses` | Situações (categoria 2 = Aberta / Finalizada / Cancelada). |
| `management_units` | Unidade gestora. |
| `contents` / `category_contents` | Secretarias (categoria de conteúdo `slug = 'secretarias'`). |

Detalhe completo em `02-MODELAGEM.md`.

## 7. Como Testar

- Cadastrar uma licitação com arquivo; conferir o registro em `biddings`, o pivot
  `biddings_has_archives` e o arquivo em `storage/licitacao/{id}/arquivos/`.
- Tentar cadastrar o mesmo `number` com a mesma modalidade e mesmas secretarias:
  deve aparecer “O Número da Licitação digitado já está em uso.”.
- Excluir uma licitação com proposta: deve retornar
  “A licitação não pode ser excluída porque já possui proposta(s).”.
- No portal, filtrar por período/modalidade/situação e conferir a URL de
  exportação (`/exportacao?...&type=xls`).
- Detalhe de uma licitação: verificar se valor e arquivos aparecem; se
  `show_value = false`, deve exibir “Indisponível”.
- Detalhes em `07-TESTES.md`.

## 8. Migração para Laravel Moderno

Reconstruir com: `FormRequest` único para store/update com `Rule::unique`
composto real (índice único em `biddings`), `Policy` por permissão
(`licitacao.create|edit|delete`), `Enum` para `statuses`/`modalidades`/`tipos`,
`API Resource` para serializar a licitação no portal, `Spatie MediaLibrary` ou
`Storage` para anexos, `Pdf`/`Excel` via queued jobs, e uma `view` migrada para
consulta materializada ou query builder. Eliminar a view SQL `licitacao` e
substituir por um `Resource`/Query Builder com os mesmos nomes de coluna usados
pelo DataTable. Detalhes em `06-MIGRACAO-MODERNA.md`.

## 9. Resumo Geral

Licitações é o módulo que publica os certames da Prefeitura. O operador cadastra
a licitação no CMS (`/cms/licitacao`), escolhe situação (Aberta/Finalizada/Cancelada),
tipo de objeto, modalidade, unidade gestora, secretarias jurisdicionadas, datas,
objeto e valor estimado, anexa o edital e decide se o valor é publicado. O
cidadão acessa `/licitacoes`, filtra, expande as propostas, abre `/licitacao/{id}`
e baixa os arquivos; o portal também exporta a lista em xls/pdf/csv/txt e lista
os contratos em `/contratos`. Os dados vivem em `biddings` e tabelas auxiliares
(`bidding_types`, `bidding_modalities`, `bidding_jurisdictionals`,
`biddings_has_archives`, `contracts`, `proposals`); o CMS lista através da view
SQL `licitacao`. O legado carrega bugs conhecidos — rota de ajax sem método,
relacionamento `BiddingType::biddings()` com coluna errada, permissões
`licitacoes.*` inexistentes usadas nos controllers de tipo/modalidade, e a
coluna `agent` de `contracts`, que só existe na v5 —, todos detalhados em
`08-GAPS-E-DIVIDAS.md`.

---

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