# 📋 Guia Completo para Criar Novos CRUDs

## 🎯 PADRÕES OBRIGATÓRIOS DO SISTEMA

**⚠️ CRÍTICO:** Todo novo CRUD DEVE seguir SEMPRE:

| Campo | Tipo | Padrão | Comportamento |
|-------|------|--------|--------------|
| **id** | serial4 | Auto-increment | PRIMARY KEY obrigatória |
| **status** | int4 | 0 (Ativo) | 0=Ativo, 2=Excluído (soft delete) |
| **empresa** | int4 | Obrigatório | Filtro em todas as queries |

**Validações Automáticas:**
- `visualizar` → Listar registros
- `criar` → Inserir novo (status=0 automático)
- `editar` → Atualizar registro
- `deletar` → Soft delete com UPDATE status=2

**⚡ DELETE NUNCA É FÍSICO:**
```sql
-- ❌ NUNCA FAZER ISSO:
DELETE FROM dim_novo_modulo WHERE id=$id

-- ✅ SEMPRE FAZER ISSO:
UPDATE dim_novo_modulo SET status=2 WHERE id=$id
```

---

## 1. Estrutura de Pastas

```
dm_novo_modulo/
├── select.php          # Query com filtros (WHERE status != 2)
├── index.php           # Listagem com permissões
├── cad.php            # Formulário (criar/editar)
├── insert.php         # Salvar/atualizar (com status=0 default)
├── delete.php         # UPDATE status=2 (soft delete)
└── filtro.php         # Tela de filtros avançados
```

---

## 2. DDL da Tabela (Exemplo CORRETO)

```sql
CREATE TABLE public.dim_novo_modulo (
	id serial4 NOT NULL,
	empresa int4 NOT NULL,
	descricao varchar NOT NULL,
	tipoconta int4,      -- Exemplo: 1=Ativo, 2=Sintético, 3=Analítico, 4=Detalhe, 5=Fechado
	natureza int4,       -- Exemplo: 0=Débito, 1=Crédito
	status int4 DEFAULT 0 NOT NULL,
	CONSTRAINT dim_novo_modulo_pk PRIMARY KEY (id)
);
```

**Obrigatório:**
- ✅ `id serial4` (auto-increment)
- ✅ `status int4 DEFAULT 0` (soft delete)
- ✅ `empresa int4` (filtro)
- ✅ `PRIMARY KEY (id)`

**Opcional (campos com múltiplos valores):**
- `tipoconta int4` - Use quando precisar múltiplas opções (exiba via CASE WHEN)
- `natureza int4` - Use quando precisar apenas 2 opções (Débito/Crédito, Sim/Não, etc)
- ⚠️ **Armazene INT, exiba descrição no SQL via CASE WHEN**

---

## 3. Prompt Padrão para o Copilot

### Para Criar do Zero:

```
Crie uma tela de cadastro seguindo o padrão de dm_grupopessoa com os seguintes dados:

**PADRÕES AUTOMÁTICOS APLICAR:**
- id: serial4 (auto-increment, primary key)
- status: int4 (0=ativo padrão, 2=excluído via soft delete)
- empresa: int4 (sempre filtrar WHERE empresa=$codempresa)
- delete.php: UPDATE status=2 (NUNCA DELETE físico)

**Nome do Módulo:** dm_novo_modulo
**Rótulo da Página:** "Novo Módulo"

**DDL da Tabela:**
CREATE TABLE public.dim_novo_modulo (
	id serial4 NOT NULL,
	empresa int4 NOT NULL,
	descricao varchar NOT NULL,
	status int4 DEFAULT 0 NOT NULL,
	CONSTRAINT dim_novo_modulo_pk PRIMARY KEY (id)
);

**Arquivos necessários:**
1. select.php - com query dos registros
2. index.php - listagem com permissões otimizadas
3. cad.php - formulário de criar/editar
4. insert.php - salvar/atualizar com validações
5. delete.php - deletar com validação
6. filtro.php - filtros avançados

**Padrões a Seguir:**
- Usar `require ('../include/autenticacao.php')`
- Usar `require ('../include/validacaopermissao.php')`
- Definir `$rot = 'dm_novo_modulo'` em todos os arquivos
- Validar permissões: visualizar, criar, editar, deletar
- Usar `validarPermissaoOuRedirecionar($rot, 'acao')`
- Index otimizado: buscar permissões 1x antes do loop
- Insert com alert de sucesso igual ao dm_motorista
- Filtro com padrão de dm_motorista (form-horizontal, selectTwo)
```

---

## 4. Checklist de Implementação

### select.php:
- [ ] `require ('../include/autenticacao.php')`
- [ ] Verificar permissão da rotina no `$_SESSION['rotina']`
- [ ] Query com `WHERE empresa = $codempresa`
- [ ] **CRÍTICO:** `AND status != 2` (listar apenas ativos)
- [ ] Aplicar filtros corretamente
- [ ] ORDER BY definido
- [ ] Resultado armazenado em `$re_postgree_dim_novo_modulo`

### index.php:
- [ ] `require ('../include/validacaopermissao.php')`
- [ ] Definir `$rot = 'dm_novo_modulo'`
- [ ] `validarPermissaoOuRedirecionar($rot, 'visualizar')`
- [ ] Layout padrão JSON
- [ ] Buscar permissões 1x: `obterTodasPermissoes($rot)`
- [ ] Loop otimizado (SEM query dentro)
- [ ] Botões condicionais com `$perm_editar` e `$perm_deletar`

### cad.php:
- [ ] `require ('../include/validacaopermissao.php')`
- [ ] Validação `strpos($rotina,'dm_novo_modulo')`
- [ ] `validarPermissaoOuRedirecionar($rot, 'visualizar')` após include
- [ ] Lógica GET com `$action == 1` para edição
- [ ] **IMPORTANTE:** Campo `status` como SELECT
  - [ ] Opção: `0 = Ativo`
  - [ ] Opção: `2 = Excluído`
- [ ] Formulário com `form-horizontal form-bordered`
- [ ] Include `cad.php` do sistema

### insert.php:
- [ ] `require ('../include/validacaopermissao.php')`
- [ ] `$rot = 'dm_novo_modulo'`
- [ ] `$empresa = $_SESSION['Codempresa']`
- [ ] Validar: `validarPermissaoOuRedirecionar($rot, 'editar')` se `$action == 1`
- [ ] Validar: `validarPermissaoOuRedirecionar($rot, 'criar')` se `else`
- [ ] **CRÍTICO:** INSERT com `status` (DEFAULT 0 ou explícito)
- [ ] Alert de sucesso com JavaScript
- [ ] Redirect para `index.php`

### delete.php:
- [ ] `require ('../include/validacaopermissao.php')`
- [ ] `validarPermissaoOuRedirecionar($rot, 'deletar')`
- [ ] **OBRIGATÓRIO:** UPDATE com `status=2` (soft delete)
  - [ ] ❌ NUNCA usar `DELETE FROM dim_novo_modulo`
  - [ ] ✅ SEMPRE usar `UPDATE dim_novo_modulo SET status=2 WHERE id=$id`
- [ ] Validar empresa: `AND empresa=$codempresa`
- [ ] Alert de sucesso
- [ ] Redirect para `index`

### filtro.php:
- [ ] `include('../include/filtros_db.php')`
- [ ] `include ('select.php')`
- [ ] Padrão de dm_motorista
- [ ] Breadcrumbs completos
- [ ] Form `form-horizontal form-bordered`
- [ ] SelectTwo para campos de relacionamento
- [ ] Botões Filtrar e Limpar

---

## 5. Variáveis Disponíveis (de autenticacao.php)

```php
$_SESSION['UsuarioID']      // ID do usuário
$_SESSION['UsuarioNome']    // Nome do usuário
$_SESSION['grupousuario']   // Grupo (nome)
$_SESSION['idgrupo']        // Grupo (ID) - AUTO PREENCHIDO
$_SESSION['Codempresa']     // Código empresa (maiúscula)
$_SESSION['codempresa']     // Código empresa (minúscula)
$_SESSION['rotina']         // Rotinas do usuário (string)

// Globais:
$usuario                    // $_SESSION['UsuarioID']
$empresa                    // $_SESSION['Codempresa']
$bdcon                      // Conexão PostgreSQL
```

---

## 6. Funções de Validação Disponíveis

```php
// Bloqueia página se sem permissão + mostra alerta
validarPermissaoOuRedirecionar($rot, 'visualizar');
validarPermissaoOuRedirecionar($rot, 'criar');
validarPermissaoOuRedirecionar($rot, 'editar');
validarPermissaoOuRedirecionar($rot, 'deletar');

// Retorna true/false (sem redirect)
$perm = validarPermissao($rot, 'editar');
if($perm) { echo "Pode editar"; }

// Retorna array com todas as permissões
$perms = obterTodasPermissoes($rot);
// $perms['visualizar'], $perms['criar'], $perms['editar'], $perms['deletar']
```

---

## 7. Exemplo Completo: select.php

```php
<?php require ('../include/autenticacao.php');
$empresa = $_SESSION['Codempresa'];
$rotina = $_SESSION['rotina'];


$query = "
	SELECT
		nm.id,
		nm.descricao,
		CASE WHEN nm.status = 0 THEN 'Ativo' ELSE 'Inativo' END as status_desc,
		nm.status
	FROM public.dim_novo_modulo nm
	WHERE nm.empresa = $codempresa
";

// Aplicar filtros se existirem
if(isset($filtros) && is_array($filtros)) {
	if(!empty($filtros['id'])) {
		$query .= " AND nm.id = " . intval($filtros['id']);
	}
	if(!empty($filtros['descricao'])) {
		$filtro_desc = pg_escape_string($filtros['descricao']);
		$query .= " AND nm.descricao ILIKE '%$filtro_desc%'";
	}
	if(isset($filtros['status']) && $filtros['status'] !== '') {
		$query .= " AND nm.status = " . intval($filtros['status']);
	}
}

$query .= " ORDER BY nm.descricao ASC";

$re_postgree_dim_novo_modulo = pg_query($bdcon, $query);
if (!$re_postgree_dim_novo_modulo) {
	echo "Erro na consulta: " . pg_last_error($bdcon);
	exit;
}
?>
```

---

## 8. Exemplo Completo: insert.php

```php
<?php require ('../include/autenticacao.php');
require ('../include/validacaopermissao.php');
$rot = 'dm_novo_modulo';

if($_SERVER["REQUEST_METHOD"] == "POST") {
	$id           	= $_POST['id'];
	if($id == null){$id = 'null';}
	$descricao    = $_POST["descricao"];
	$action       = $_POST["action"];
	$empresa      = $_POST["empresa"];
	$status       = $_POST["status"];
	if($status == null || $status == ''){$status = 0;}

	if($action == 1) {
		// Validar permissão de editar
		validarPermissaoOuRedirecionar($rot, 'editar');
		$sql = "UPDATE public.dim_novo_modulo
				SET descricao='$descricao', 
				status=$status
				WHERE id=$id AND empresa=$empresa
				";
	} else {
		// Validar permissão de criar
		validarPermissaoOuRedirecionar($rot, 'criar');
		$sql = "INSERT INTO public.dim_novo_modulo (empresa, descricao, status) 
				VALUES ($empresa,'$descricao',$status)";
	}

	$res = pg_query($bdcon,$sql);
	
	if($res){
		echo "<script language='javascript' type='text/javascript'>
		alert('Cadastro realizado com sucesso');
		window.location.href='index';
		</script>";
		exit;
	}else{
		echo pg_last_error($bdcon);
		exit;
	}
}
?>
```

---

## 9. Passo-a-Passo Rápido

### Step 1: Criar pasta
```
mkdir dm_novo_modulo
```

### Step 2: Criar banco de dados
```sql
CREATE TABLE public.dim_novo_modulo (...);
```

### Step 3: Preparar DDL em texto
```
DDL aqui...
```

### Step 4: Usar prompt no Copilot
Copie o prompt padrão acima + seu DDL

### Step 5: Testar cada página
- index.php → Listagem
- cad.php → Criar novo
- cad.php?id=1 → Editar
- delete.php?id=1 → Deletar

### Step 6: Configurar permissões
Via `/sis004a_grupopermissao/` atribuir rotina + acoes ao grupo

---

## 10. Troubleshooting

| Problema | Solução |
|----------|---------|
| "Você não tem permissão" | Verificar `/sis004a_grupopermissao/` |
| Listagem vazia | Verificar `$empresa` no select.php ou `status != 2` |
| **Registros sumiram após deletar** | Normal! Soft delete (status=2) os oculta. Não foram perdidos. |
| Botão Alterar não aparece | Verificar se tem permissão `editar` |
| Insert sem feedback | Verificar se tem alert de sucesso |
| Filtro não funciona | Verificar se `filtros_db.php` está incluído |
| Deletar dá erro de chave estrangeira | Use UPDATE status=2, não DELETE direto |

---

## 11. ⚠️ Dicas Críticas sobre Status e Soft Delete

### Nunca fazer isso:
```php
// ❌ ERRADO - Apaga registros permanentemente
$sql = "DELETE FROM dim_novo_modulo WHERE id=$id";
pg_query($bdcon, $sql);
```

### Sempre fazer isso:
```php
// ✅ CORRETO - Marca como deletado
$sql = "UPDATE dim_novo_modulo SET status=2 WHERE id=$id AND empresa=$empresa";
pg_query($bdcon, $sql);
```

### Regras do Status:
- `0` = Ativo (padrão ao inserir)
- `2` = Excluído (soft delete via UPDATE)
- **NUNCA** use `DELETE FROM` em nenhum arquivo
- Sempre filtrar: `WHERE status != 2` nas listagens
- Insert automático: `DEFAULT 0` na DDL

### Se precisar restaurar:
```sql
-- Recuperar um registro
UPDATE dim_novo_modulo SET status=0 WHERE id=123 AND empresa=1;

-- Listar TODOS (incluindo deletados)
SELECT * FROM dim_novo_modulo WHERE empresa=1 ORDER BY id;

-- Listar SÓ deletados
SELECT * FROM dim_novo_modulo WHERE empresa=1 AND status=2;
```

---

## 12. Links Úteis

- **Validação de Permissões:** `/include/validacaopermissao.php`
- **Exemplos:** `/include/EXEMPLO_VALIDACAOPERMISSAO.php`
- **Teste Sistema:** `/include/teste_validacaopermissao.php`
- **Padrão Motorista:** `/dm_motorista/`
- **Padrão Grupo Pessoa:** `/dm_grupopessoa/`

---

## 13. Documentação de Referência

Para cada novo CRUD, atualize:
- Tabela `sis_rotina` (inserir rotina)
- Tabela `sis_permissaogrupo` (definir permissões por grupo)
- Este documento (adicione nova rotina na lista)

---

**Última atualização:** 27/01/2026  
**Versão:** 2.0  
**Status:** Produção ✅  
**Padrões:** id (serial), status (soft delete), validações automáticas
