# Licitações — Arquitetura

> Versão analisada: `v6` (Laravel 5.5 / PHP 7.2).
> Referência de origem (v5): `v5/app/Http/Controllers/Prefecture/Bidding/BiddingController.php`.

---

## 1. Visão geral das camadas

O módulo tem **duas entradas independentes** que compartilham a mesma base de dados:

```
                    ┌────────────────────── CMS (/cms) ──────────────────────┐
Form (blade)  →  Prefecture\Bidding\BiddingController
                        │  (middleware check.route.permission)
                        ▼
                  BiddingRequest  (regras + mensagens)
                        ▼
                  BiddingRepositoryDefaultImpl
                  (structureUpInsert: datas BR→US, strip_tags(local))
                        ▼
                  App\Prefecture\Bidding  (Eloquent)
                        ▼
                  PostgreSQL: biddings + bidding_jurisdictionals + biddings_has_archives
```

```
                    ┌──────────────────── Portal (público) ────────────────────┐
GET /licitacoes  →  Portal\BiddingsController@index
                        ▼
                  App\Http\Filter\FilterBiddings (filtros)
                        ▼
                  App\Prefecture\Bidding (Eloquent, scopes de eager loading)
                        ▼
                  view portal.layouts.{layout}.licitacao.index

GET /licitacao/{id} → Portal\BiddingsController@indexShow
                        ▼
                  scopeRelationsBidding() + Archive::where('biddings_id')
                        ▼
                  view portal.layouts.{layout}.licitacao.show
```

O CMS **não** usa o portal e o portal **não** usa o controller do CMS.
A única interseção é a tabela `biddings` e a view SQL `licitacao`.

## 2. Classes envolvidas (caminho real e papel)

### 2.1 Controllers (CMS)

| Classe | Caminho | Papel |
|---|---|---|
| `BiddingController` | `v6/app/Http/Controllers/Prefecture/Bidding/BiddingController.php` | CRUD de licitações, upload de arquivos, exclusão individual e em lote, log de auditoria. |
| `BiddingTypeController` | `v6/app/Http/Controllers/Prefecture/Bidding/BiddingTypeController.php` | CRUD de tipos de objeto (`bidding_types`). |
| `BiddingModalityController` | `v6/app/Http/Controllers/Prefecture/Bidding/BiddingModalityController.php` | CRUD de modalidades (`bidding_modalities`). |
| `ContractController` | `v6/app/Http/Controllers/Prefecture/ContractController.php` | CRUD de contratos; monta os selects de propostas/licitações com SQL cru. |
| `DatatableController` | `v6/app/Http/Controllers/Prefecture/DatatableController.php` | `get_licitacao()` / `get_contratos()` alimentam os DataTables do CMS a partir das views SQL. |

### 2.2 Controllers (Portal)

| Classe | Caminho | Papel |
|---|---|---|
| `BiddingsController` | `v6/app/Http/Controllers/Portal/BiddingsController.php` | Listagem, busca, detalhe, exportação (xls/pdf/csv/txt), paginação manual. |
| `ContractController` | `v6/app/Http/Controllers/Portal/ContractController.php` | Listagem e detalhe de contratos; filtros próprios. |

### 2.3 Form Requests

| Classe | Caminho | Valida |
|---|---|---|
| `BiddingRequest` | `v6/app/Http/Requests/BiddingRequest.php` | Cadastro/edição de licitação (regras distintas para `licitacao.store` e `licitacao.update`). |
| `BiddingTypeRequest` | `v6/app/Http/Requests/BiddingTypeRequest.php` | `name` obrigatório, máx. 120. |
| `BiddingModalityRequest` | `v6/app/Http/Requests/BiddingModalityRequest.php` | `name` obrigatório, máx. 120. |
| `ContractRequest` | `v6/app/Http/Requests/ContractRequest.php` | Número, datas, `bidding_id` e `value` do contrato. |
| `SelectRule` | `v6/app/Rules/SelectRule.php` | Regra usada nos selects: reprova o valor `'0'`. |

### 2.4 Repositórios

| Interface | Implementação | Papel |
|---|---|---|
| `v6/app/Repositories/Contracts/IBiddingRepository.php` | `v6/app/Repositories/Eloquent/Prefecture/Bidding/BiddingRepositoryDefaultImpl.php` | Normaliza datas/valor e sobrescreve `destroy()` para desanexar as secretarias. |
| `v6/app/Repositories/Contracts/IContractRepository.php` | `v6/app/Repositories/Eloquent/Prefecture/Contract/ContractRepositoryDefaultImpl.php` | Placeholder: `structureUpInsert()` devolve `[]`. |
| `v6/app/Repositories/Contracts/IArchiveRepository.php` | (usada por `BiddingController` via injeção) | Upload de arquivos do edital. |
| — | `v6/app/Repositories/Repository.php` | Base abstrata: `upInsert()`, `destroy()`, `destroyAll()`, `destroyWithRelation()`. |

As três interfaces de contrato estão **vazias** (`interface IBiddingRepository { }`),
herdando o contrato implícito da classe base `Repository`.

### 2.5 Models

| Classe | Caminho | Papel |
|---|---|---|
| `Bidding` | `v6/app/Http/Model/Prefecture/Bidding.php` | Eloquent da tabela `biddings`, `SoftDeletes`, presenter, scopes de eager loading e accessors de data/valor. |
| `BiddingType` | `v6/app/Http/Model/Prefecture/BiddingType.php` | `bidding_types`. |
| `BiddingModality` | `v6/app/Http/Model/Prefecture/BiddingModality.php` | `bidding_modalities`. |
| `BiddingHasArchive` | `v6/app/Http/Model/Prefecture/BiddingHasArchive.php` | Pivot `biddings_has_archives`. |
| `BiddingJurisdictionals` | `v6/app/Http/Model/Prefecture/BiddingJurisdictionals.php` | Secretarias jurisdicionadas. |
| `Contract` | `v6/app/Http/Model/Prefecture/Contract.php` | `contracts` (com `bidding_id` na v6). |
| `Proposal` | `v6/app/Http/Model/Prefecture/Proposal.php` | Propostas; `hasMany(Contract)`. |
| `Archive` | `v6/app/Http/Model/Prefecture/Archive.php` | Arquivos; `belongsToMany(Bidding)` pela pivot. |

Namespace efetivo: `App\Prefecture\*` (mapeado por classmap para
`v6/app/Http/Model/Prefecture/`).

### 2.6 Serviços / filtros / presenters / exports

| Classe | Caminho | Papel |
|---|---|---|
| `FilterBiddings` | `v6/app/Http/Filter/FilterBiddings.php` | Aplica todos os filtros da listagem pública. |
| `BiddingPresenter` | `v6/app/Http/Presenters/BiddingPresenter.php` | `getStyleHasProposal()`, `getStyleColorTd()` (cor por `statuses_id`). |
| `ContractPresenter` | `v6/app/Http/Presenters/ContractPresenter.php` | Formatação de datas e valor do contrato. |
| `BiddingsExport` | `v6/app/Exports/BiddingsExport.php` | `FromView` sobre `exports.biddings` (xls/csv). |
| `ContractsExportView` | `v6/app/Exports/ContractsExportView.php` | Export de contratos (usado pelo fluxo de contratos). |

### 2.7 Traits e helpers

| Item | Caminho | Uso no módulo |
|---|---|---|
| `AppTrait` | `v6/app/Http/Traits/AppTrait.php` | `toUSDataFormat()`, `toUSDataHourFormat()`, `toBRCurrencyFormat()`, `traitRequest()`. |
| `FileTrait` | `v6/app/Http/Traits/FileTrait.php` | `getFileName()`, `deleteFile()`. |
| `has_access()` | `v6/app/Library/Helper/appHelpers.php` | Verificação de permissão nos controllers e nas views. |
| `CheckRoutePermission` | `v6/app/Http/Middleware/CheckRoutePermission.php` | Middleware aplicado no construtor de `BiddingController` e `ContractController`. |

## 3. Diagrama de fluxo — cadastro no CMS

```
Navegador
  │  POST /cms/licitacao  (multipart: number, statuses_id, ..., archive[][0], archive[][description])
  ▼
Route::resource('licitacao')  →  nome da rota: licitacao.store
  ▼
Prefecture\Bidding\BiddingController@store
  │  1. Checagem de unicidade: Bidding::whereHas('contents', jurisdictionados)
  │     ->where('number')->where('bidding_modalities_id')
  │     → se encontrar, flash de erro e redirect()->back()->withInput()
  │  2. $request->merge(['is_show' => isset($request->is_show)])
  ▼
BiddingRequest (authorize = true, rules de 'create')
  │  status failed → redirect()->back() com erros
  ▼
BiddingRepositoryDefaultImpl::upInsert($request)
  │  DB::transaction( structureUpInsert( traitRequest( request->request->all() ) ) )
  │  → publication_edital_date em d/m/Y → Y-m-d
  │  → competition_date em d/m/Y H:i → Y-m-d H:i
  │  → homologation_date em d/m/Y → Y-m-d
  │  → local com strip_tags
  │  → updateOrCreate(['id' => null], $data)  (fill respeita $fillable)
  ▼
Bidding gravado  ──►  $licitacao->contents()->attach($jurisdicionado)
  │
  └► extractedToArchive(): para cada $request->archive[]
        → archiveRepository->upInsert() (grava em archives)
        → $licitacao->archives()->attach($insertArchive)
        → activity()->log('Cadastro de arquivo')
  ▼
flash('Licitação cadastrada com sucesso.') → redirect route('licitacao.index')
```

## 4. Diagrama de fluxo — listagem pública

```
GET /licitacoes?dt_inicial=...&number=...
  ▼
Portal\BiddingsController@index
  │  Carrega: modalidades, tipos, situacoes (status_category_id=2),
  │  secretarias (contents da categoria 'secretarias'), participantes (Person),
  │  min/max de value, locais distintos
  ▼
FilterBiddings::filter($request)
  │  scope relationsBiddingWithProposal() + when(...) por:
  │  number, process_number, statuses_id, bidding_modalities_id, local,
  │  bidding_types_id, object (translate/ilike), value (whereBetween),
  │  proponent (whereHas proposals.proponents), dt_inicial, dt_final, show
  ▼
orderByRaw('homologation_date IS NULL, homologation_date DESC, publication_edital_date DESC')
  ▼
if Route::currentRouteName() == 'exportacao'  → export($result, $request->type)
if request()->ajax()                          → response()->json($result)
else                                          → LengthAwarePaginator (10 por página)
  ▼
view portal.layouts.{config('layouts')}.licitacao.index
```

## 5. Dependências externas (composer)

| Pacote | Versão em `v6/composer.json` | Uso |
|---|---|---|
| `laravel/framework` | `5.5.*` | base |
| `cartalyst/sentinel` | `2.0.*` | sessão, `Sentinel::getUser()`, `hasAnyAccess` |
| `laracasts/presenter` | `^0.2.2` | `BiddingPresenter`, `ContractPresenter` |
| `maatwebsite/excel` | `^3.1` | `Excel::download(new BiddingsExport(...))` (xls/csv) |
| `barryvdh/laravel-dompdf` | `^0.8.7` | `PDF::loadView('exports.biddings')` (pdf) |
| `yajra/laravel-datatables` | `^1.5` | DataTables do CMS (`get_licitacao`) |
| `spatie/laravel-activitylog` | `^2.8` | log de auditoria (`activity()->performedOn(...)`) |
| `php` | `>=7.2.0` | runtime |

Bibliotecas client-side usadas nas telas: jQuery + DataTables, jQuery UI
(slider de faixa de valor), Summernote (objeto), Bootstrap 3 WYSIHTML5, jsPDF +
jsPDF-AutoTable (PDF pelo navegador).

## 6. Nota sobre o `getTemplateActived()`

`v6/app/Http/Controllers/Portal/...` herda de `App\Http\Controllers\Admin\Controller`,
que expõe `getTemplateActived()`
(`v6/app/Http/Controllers/Admin/Controller.php:39-49`): lê
`Configuration::where('key', 'layout')->first()->value` e monta
`portal.layouts.{layout}.licitacao.*`. O valor cadastrado no banco de
desenvolvimento é `modelo1`. Se o layout ativo for `default`, **não existe**
`portal/layouts/default/licitacao/` — a listagem quebraria com view inexistente.
