# Fornecedores — Modelagem de Dados

> Estrutura de dados do módulo. Fonte: schema real do banco
> `prefeituras_v5`.

---

## 1. `suppliers`

Criada por `v6/database/migrations/2021_01_25_160407_create_suppliers_table.php`.

| Coluna | Tipo | Null | Default | Observação |
|---|---|---|---|---|
| `id` | integer | não | `nextval('suppliers_id_seq')` | PK |
| `name` | varchar(191) | **não** | — | razão social / nome fantasia |
| `slug` | varchar(191) | **não** | — | gerado por `Str::slug($request->name)` |
| `email` | varchar(191) | **não** | — | e-mail de contato |
| `site` | varchar(191) | **não** | — | site |
| `phone` | varchar(191) | **não** | — | telefone (só dígitos) |
| `image` | varchar(191) | sim | — | caminho relativo do logotipo |
| `icon` | varchar(191) | sim | — | caminho relativo do ícone |
| `address` | varchar(500) | sim | — | endereço |
| `locale` | varchar(500) | sim | — | **URL do embed do Google Maps** |
| `fornecedor_ativo` | boolean | sim | — | marca o fornecedor exibido |
| `whatsapp` | varchar(191) | sim | — | só dígitos |
| `created_at` / `updated_at` | timestamp(0) | sim | — | |
| `deleted_at` | timestamp(0) | sim | — | `SoftDeletes` |

### 1.1 Colunas removidas (herança do schema antigo)

O model `App\Http\Model\Prefecture\Supplier` ainda lista no `$fillable`:

```php
protected $fillable = [
    'name', 'image', 'icon', 'telefone', 'email', 'endereco',
    'locale', 'phone', 'address', 'slug', 'site', 'fornecedor_ativo', 'whatsapp'
];
```

`telefone` e `endereco` **não existem** na tabela (foram renomeados para
`phone` e `address`). São resíduos de um esquema anterior; a view SQL
`fornecedores` os expõe como alias.

### 1.2 Migrations

| Migration | Efeito |
|---|---|
| `v6/database/migrations/2021_01_25_160407_create_suppliers_table.php` | cria `suppliers` |
| `v6/database/migrations/2022_05_09_112612_add_column_to_suppliers_table.php` | adiciona `fornecedor_ativo` (boolean, nullable) |
| `v6/database/migrations/2025_05_06_082956_update_suppliers_address_values.php` | corrige os endereços dos fornecedores de exemplo (Máxima/PBSoft) |
| `v5/database/migrations/2026_04_06_113000_alter_suppliers_table_nullable.php` | **existe só na v5**: torna `email` e `site` nullable. **Não foi portada para a v6** — por isso, na v6, `email` e `site` são `NOT NULL` |

> A ausência dessa migration na v6 é uma divergência de schema entre as
> duas versões. Se a v7 precisar aceitar fornecedor sem e-mail, é
> preciso portar a alteração (ou decidir o novo contrato).

---

## 2. View SQL `fornecedores`

Criada fora do conjunto de migrations do projeto (view já existente na
base). Definição extraída do banco:

```sql
SELECT row_number() OVER (ORDER BY s.created_at DESC) AS value,
    s.name AS titulo,
    s.email,
    s.phone AS telefone,
    s.address AS endereco,
    s.icon AS icone,
    s.image AS imagem,
    s.id,
    s.fornecedor_ativo AS status
   FROM suppliers s
  WHERE s.deleted_at IS NULL
  ORDER BY s.created_at DESC;
```

É consumida por `Prefecture\DatatableController@get_fornecedor`
(`v6/app/Http/Controllers/Prefecture/DatatableController.php:159-163`):

```php
public function get_fornecedor()
{
    $supplier = DB::table('fornecedores')->get();
    return DataTables::of($this->struct_views($supplier, 'supplier'))->make(true);
}
```

> A listagem do CMS **não** usa o model `Supplier` — usa a view. Isso
> significa que `slug`, `locale` e `whatsapp` **não** chegam ao
> front-end da tabela (o WhatsApp é exibido apenas na página de Suporte).

---

## 3. `modulos` e `resources`

| Item | Valor |
|---|---|
| `modulos` | id **6**, name "Fornecedores", slug `fornecedores`, `status = true` |
| `resources` | **NENHUMA LINHA** com slug `supplier` (nem `fornecedores`) |
| `menu_orders` | **NENHUMA LINHA** para `fornecedores` |

Sem recurso, as permissões `supplier.index` e `supplier.create` (usadas
na view e no menu) **não podem ser concedidas** a nenhum perfil: só
`super-admin` passa.

---

## 4. Relacionamentos

Nenhum. `suppliers` é uma tabela isolada (sem FK de entrada ou saída).

---

## 5. Seed

`v6/database/seeds/SuplierTableSeeder.php`:

```php
DB::table('suppliers')->truncate();

DB::table('suppliers')->insert([
    [
        'name' => 'Máxima Tecnologia',
        'email' => 'suporte@maxima.inf.br',
        'site' => 'https://suporte.maxima.inf.br',
        'phone' => '8341410231',
        'slug' => 'maxima-tecnologia',
        'address' => 'Av. Expedicionários, 481, Expedicionários, Sala 03 - João Pessoa - PB, 58041-010',
        'locale' => 'https://www.google.com/maps/embed?pb=!1m18!1m12!...',
        'image' => 'img/icons_fornecedores/maxima-tecnologia.png',
        'icon' => 'img/icons_fornecedores/icon-maxima.png',
        'fornecedor_ativo' => true,
    ],
    [ 'name' => 'PBSoft', ... ],
    [ 'name' => 'PublicSoft', ... ],
]);
```

| Fornecedor | `fornecedor_ativo` | `whatsapp` |
|---|---|---|
| Máxima Tecnologia | `true` | — |
| PBSoft | — | `83996322012` |
| PublicSoft | — | — |

> O seeder faz **`truncate`** — executá-lo apaga todos os fornecedores
> cadastrados. Em um ambiente de produção com o módulo em uso, o seed
> deve ser removido do fluxo de instalação.

---

## 6. Storage (arquivos)

| Campo | Diretório (disk `public`) | Observação |
|---|---|---|
| `image` | `storage/app/public/img/images_fornecedores/` | logotipo exibido na página de Suporte |
| `icon` | `storage/app/public/img/icons_fornecedores/` | ícone exibido na listagem |

O nome do arquivo é gerado por `FileTrait::getFileName()`:
`uniqid('', false) . str_random(5) . '.' . extensao`, em minúsculas.

---

## 7. Observações de modelagem para a v7

1. **`slug` deve ser único** e não pode ser recalculado a cada edição
   (hoje `upInsert` sempre refaz `Str::slug($request->name)` — renomear
   o fornecedor muda o slug).
2. **`fornecedor_ativo` deve ser um booleano com restrição de
   unicidade** ("no máximo um ativo"). Hoje nada garante isso: a view
   SQL e as telas usam `->first()`.
3. **Remover `telefone`/`endereco`** do `$fillable` e da view SQL, ou
   renomear as colunas de forma consistente.
4. **`locale` deve ser validado como URL** (o `SupplierRequest` só exige
   `required`).
5. **`email` e `site` NOT NULL** — a v5 já os havia tornado nullable.
   Decidir o contrato da v7.
6. **Adicionar `deleted_at`aware** — já existe; só garantir que a view
   SQL filtre (ela já filtra).
7. Se o fornecedor for único por instalação (o caso), talvez nem precise
   de `fornecedor_ativo`: bastaria um único registro. Mas o desenho atual
   (vários, um ativo) é mais flexível.
