# 03 — Banco de Dados

## Bancos de Dados

O sistema utiliza dois tipos de banco:

| Banco | Propósito | Tabelas Principais |
|-------|-----------|-------------------|
| `antigravity_master` | Multi-tenant: usuários globais e clientes | `clientes`, `usuarios_globais`, `usuario_cliente` |
| `antigravity_{codigo}` | Dados isolados por cliente | `demanda`, `tarefa`, `usuario`, etc. |

---

## antigravity_master — Tabelas

### `clientes`
| Coluna | Tipo | Descrição |
|--------|------|-----------|
| `cliente_id` | INT PK | ID do cliente |
| `codigo` | VARCHAR | Código único (ex: `dev`, `bpoconsig`) — usado como identificador nos requests |
| `nome` | VARCHAR | Nome display do cliente |
| `ativo` | INT | 1=ativo, 0=inativo |

### `usuarios_globais`
| Coluna | Tipo | Descrição |
|--------|------|-----------|
| `usuario_global_id` | INT PK | ID global do usuário |
| `nome` | VARCHAR | Nome completo |
| `email` | VARCHAR | Email único — serve como username |
| `senha_hash` | VARCHAR | MD5 da senha |
| `ativo` | INT | 1=ativo, 0=inativo |

### `usuario_cliente`
| Coluna | Tipo | Descrição |
|--------|------|-----------|
| `usuario_cliente_id` | INT PK | ID do relacionamento |
| `usuario_global_id` | INT FK | Ref → usuarios_globais |
| `cliente_id` | INT FK | Ref → clientes |
| `usuario_id_local` | INT | ID do usuário na tabela `usuario` do BD cliente |
| `ativo` | INT | 1=ativo, 0=inativo no cliente específico |

### `push_tokens` *(por BD de cliente, criada via migrate_notifications_db.php)*
| Coluna | Tipo | Descrição |
|--------|------|-----------|
| `push_token_id` | INT PK | ID do token |
| `usuario_id` | INT | ID local do usuário |
| `token` | VARCHAR(500) | Token Expo Push (ex: `ExponentPushToken[xxx]`) |
| `platform` | VARCHAR(10) | `ios` ou `android` |
| `created_at` / `updated_at` | DATETIME | Timestamps |

### `notificacoes` *(por BD de cliente)*
| Coluna | Tipo | Descrição |
|--------|------|-----------|
| `notificacao_id` | INT PK | ID da notificação |
| `usuario_id` | INT | Destinatário |
| `tipo` | VARCHAR(50) | `tarefa`, `demanda`, `afazer`, `revisao` |
| `titulo` | VARCHAR(200) | Título da notificação |
| `mensagem` | VARCHAR(500) | Corpo da mensagem |
| `referencia_id` | INT | ID do item (tarefa_id, tarefarapida_id) |
| `lida` | TINYINT | 0=não lida, 1=lida |
| `data_cadastro` | DATETIME | Momento de criação |

---

## BD Cliente — Tabelas Completas

### `usuario` — Usuários do cliente
| Coluna | Tipo | Descrição |
|--------|------|-----------|
| `usuario_id` | INT PK | ID local |
| `cpf` | VARCHAR | Email (campo historicamente chamado de CPF) |
| `nome` | VARCHAR(80) | Nome completo |
| `senha` | VARCHAR(32) | MD5 (legado; senha real está no master) |
| `cargo` | VARCHAR(1) | `0`=executor, `1`-`4`=gestores por nível |
| `divisao_id` | INT FK | Divisão do usuário |
| `login` | VARCHAR | Login/apelido |
| `admin` | INT | 1=administrador do sistema (acesso a Configurações) |
| `ativo` | INT | 1=ativo, 0=inativo |
| `visao` | INT | 0=normal; 1=visão expandida |
| `custo_hora` | DECIMAL | Custo-hora para cálculo de SGF |

### `demanda` — Projetos
| Coluna | Tipo | Descrição |
|--------|------|-----------|
| `demanda_id` | INT PK | ID do projeto |
| `descricao` | VARCHAR(500) | Título do projeto |
| `resumo` | LONGTEXT | Descrição detalhada |
| `prazo` | DATETIME | Data fim do projeto |
| `data_inicio` | DATETIME | Data início |
| `data_cadastro` | DATETIME | Data de criação |
| `ultima_atualizacao` | TIMESTAMP | Última modificação (auto) |
| `demanda_status_id` | INT FK | Status do projeto |
| `demanda_progresso_id` | INT FK | Percentual de progresso |
| `demanda_tema_id` | INT FK | Tema/categoria |
| `divisao_id` | INT FK | Divisão responsável |
| `usuario_id` | INT | Criador do projeto |
| `NUP` | VARCHAR | Número único do processo |
| `OS` | VARCHAR | Ordem de serviço |
| `gantt` | INT | 0=sem Gantt; 1=exibe Gantt |
| `orcamento` | DECIMAL | Orçamento previsto |

### `demanda_status` — Status dos Projetos
| ID | Descrição |
|----|-----------|
| 1 | Ativa |
| 2 | Concluída |
| 3 | Cancelada |
| 4 | Aguarda Registro de Resultados |
| *(configurável)* | Pausada, Planejada, etc. |

### `tarefa` — Tarefas de Projetos
| Coluna | Tipo | Descrição |
|--------|------|-----------|
| `tarefa_id` | INT PK | ID da tarefa |
| `demanda_id` | INT FK | Projeto pai |
| `descricao` | VARCHAR(1000) | Descrição da tarefa |
| `data_cadastro` | DATETIME | Data de criação |
| `ultima_atualizacao` | TIMESTAMP | Auto-atualizado |
| `prazo` | DATETIME | Prazo de entrega |
| `data_inicio` | DATETIME | Data de início |
| `data_urgencia` | DATETIME | Data de urgência (opcional) |
| `data_conclusao` | DATETIME | Quando foi concluída |
| `tipo_tarefa` | INT | Tipo (1=padrão) |
| `tarefa_status_id` | INT FK | Status atual |
| `usuariodemandado_id` | INT FK | Responsável pela execução |
| `owner_id` | INT FK | Criador da tarefa |
| `distribuicao` | INT | 0=atribuída; 1=aguarda distribuição |
| `distribuicao_divisao_id` | INT FK | Divisão para distribuição |

### `tarefa_status` — Status das Tarefas
| ID | Descrição | Ordem | Cargo Notificado |
|----|-----------|-------|-----------------|
| 1 | Não Iniciada | 1 | — |
| 2 | Iniciada | 2 | — |
| 9 | Suspensa | 3 | — |
| 10 | Aguardando Providência Externa | 4 | — |
| 3 | Em análise - #NIVEL_ESTRUTURA1# | 5 | cargo=1 |
| 4 | Analisada - #NIVEL_ESTRUTURA1# | 6 | cargo=0 |
| 5 | Em análise - #NIVEL_ESTRUTURA2# | 7 | cargo=2 |
| 6 | Analisada - #NIVEL_ESTRUTURA2# | 8 | cargo=1 |
| 11 | Em análise - #NIVEL_ESTRUTURA3# | 9 | cargo=3 |
| 13 | Analisada - #NIVEL_ESTRUTURA3# | 10 | cargo=2 |
| 14 | Em análise - #NIVEL_ESTRUTURA4# | 11 | cargo=4 |
| 15 | Analisada - #NIVEL_ESTRUTURA4# | 12 | cargo=3 |
| 7 | Concluída | 13 | — |
| 8 | Cancelada | 14 | — |

### `tarefa_historico` — Histórico de Status de Tarefas
| Coluna | Tipo | Descrição |
|--------|------|-----------|
| `tarefa_historico_id` | INT PK | ID |
| `tarefa_id` | INT FK | Tarefa |
| `tarefa_status_id` | INT FK | Status registrado |
| `usuario_id` | INT FK | Quem fez a mudança |
| `data_atualizacao` | DATETIME | Quando ocorreu |

### `tarefa_todo` — Afazeres (sub-itens de tarefa)
| Coluna | Tipo | Descrição |
|--------|------|-----------|
| `tarefa_todo_id` | INT PK | ID |
| `tarefa_id` | INT FK | Tarefa pai |
| `descricao` | VARCHAR(1000) | Descrição do afazer |
| `ordem` | INT | Posição na lista (ordenável) |
| `tarefa_todo_status_id` | INT | 1=pendente, 2=concluído |
| `usuario_id` | INT FK | Responsável |
| `data_cadastro` | DATETIME | Data de criação |
| `observacao` | VARCHAR | Observação/comentário livre |

### `tarefa_providencia` — Histórico de Providências
| Coluna | Tipo | Descrição |
|--------|------|-----------|
| `tarefa_providencia_id` | INT PK | ID |
| `tarefa_id` | INT FK | Tarefa |
| `demanda_id` | INT FK | Projeto (redundância para queries) |
| `descricao` | VARCHAR(1000) | Texto da providência |
| `usuario_id` | INT FK | Quem registrou |
| `data_cadastro` | DATETIME | Quando |
| `esforco` | INT | Esforço em horas (opcional) |

### `tarefa_anexo` — Anexos de Tarefas
| Coluna | Tipo | Descrição |
|--------|------|-----------|
| `tarefa_anexo_id` | INT PK | ID |
| `tarefa_id` | INT FK | Tarefa |
| `path` | VARCHAR(500) | Caminho relativo no servidor legado |
| `nome_arquivo` | VARCHAR | Nome gerado (timestamp + nome original) |
| `gcs_path` | VARCHAR | Caminho no GCS bucket |
| `descricao` | VARCHAR | Descrição do arquivo |
| `type` | VARCHAR | MIME type |
| `size` | INT | Tamanho em bytes |
| `usuario_id` | INT FK | Quem fez upload |
| `data_cadastro` | DATE | Data |

### `tarefa_link` — Links de Tarefas
| Coluna | Tipo | Descrição |
|--------|------|-----------|
| `tarefa_link_id` | INT PK | ID |
| `tarefa_id` | INT FK | Tarefa |
| `nome_arquivo` | VARCHAR | Descrição/nome do link |
| `link` | VARCHAR(2000) | URL |
| `usuario_id` | INT FK | Quem adicionou |
| `data_cadastro` | DATETIME | Data |

### `tarefa_conclusao` — Registro de Ciência de Conclusão
| Coluna | Tipo | Descrição |
|--------|------|-----------|
| `tarefa_conclusao_id` | INT PK | ID |
| `tarefa_id` | INT FK | Tarefa concluída |
| `usuario_id` | INT FK | Usuário que deve tomar ciência |
| `ciencia` | INT | 0=pendente, 1=ciente |
| `data_ciencia` | DATETIME | Quando tomou ciência |
| `data_atualizacao` | DATETIME | Última atualização |

### `tarefarapida` — Demandas Rápidas
| Coluna | Tipo | Descrição |
|--------|------|-----------|
| `tarefarapida_id` | INT PK | ID |
| `descricao` | VARCHAR(1000) | Descrição |
| `tarefarapida_prioridade_id` | INT FK | 1=Baixa, 2=Média, 3=Alta |
| `visibilidade` | INT | 0=privada, 1=visível ao criador |
| `data_cadastro` | DATETIME | Criação |
| `ultima_atualizacao` | TIMESTAMP | Auto |
| `usuario_id` | INT FK | Criador |
| `usuariodemandado_id` | INT FK | Destinatário |
| `tarefarapida_status_id` | INT FK | 1=Ativa, 2=Concluída, 3=Cancelada |
| `data_conclusao` | DATETIME | Quando concluiu |

### `demanda_recursos` — Equipe do Projeto
| Coluna | Tipo | Descrição |
|--------|------|-----------|
| `demanda_recursos_id` | INT PK | ID |
| `demanda_id` | INT FK | Projeto |
| `usuario_id` | INT FK | Membro da equipe |
| `status` | INT | 1=ativo, 0=inativo |

### `demanda_nota` — Notas/Comentários do Projeto
| Coluna | Tipo | Descrição |
|--------|------|-----------|
| `demanda_nota_id` | INT PK | ID |
| `demanda_id` | INT FK | Projeto |
| `nota` | VARCHAR(5000) | Texto do comentário |
| `usuario_id` | INT FK | Autor |
| `data_cadastro` | DATETIME | Data |

### `demanda_custo` — Custos do Projeto
| Coluna | Tipo | Descrição |
|--------|------|-----------|
| `demanda_custo_id` | INT PK | ID |
| `demanda_id` | INT FK | Projeto |
| `categoria_custo_id` | INT FK | Categoria do custo |
| `centro_custo_id` | INT FK | Centro de custo |
| `beneficiario_id` | INT FK | Usuário beneficiário |
| `valor` | DECIMAL | Valor do custo |
| `observacao` | VARCHAR(2000) | Justificativa |
| `usuario_registro_id` | INT FK | Quem registrou |
| `data_cadastro` | DATETIME | Data |
| `necessita_aprovacao` | INT | 1=precisa aprovação, 0=automático |

### `autoriza_custo` — Histórico de Aprovação de Custos
| Coluna | Tipo | Descrição |
|--------|------|-----------|
| `autoriza_custo_id` | INT PK | ID |
| `demanda_custo_id` | INT FK | Custo associado |
| `status_id` | INT | 0=pendente, 1=aprovado, 2=reprovado |
| `autorizador_id` | INT FK | Quem aprovou/reprovou |
| `data_autorizacao` | DATETIME | Quando |
| `ultima_atualizacao` | DATETIME | Atualização |
| `observacao` | VARCHAR(2000) | Comentário do aprovador |

### `alcada_custo` — Regras de Alçada para Aprovação
| Coluna | Tipo | Descrição |
|--------|------|-----------|
| `alcada_custo_id` | INT PK | ID |
| `categoria_custo_id` | INT FK | Categoria afetada |
| `cargo` | INT | Cargo que pode aprovar |
| `autorizacao` | INT | 1=pode autorizar |
| `limite` | DECIMAL | Valor limite para autorização |

### `constantes` — Configurações Gerais do Sistema
| Coluna | Tipo | Descrição |
|--------|------|-----------|
| `constantes_id` | INT PK | Always 1 |
| `niveis_gerenciais` | VARCHAR | Nomes dos cargos (ex: "Executor,Gestor,Coordenador,...") |
| `niveis_estrutura` | VARCHAR | Nomes estruturais (ex: "Divisão,Coordenação,Diretoria,Presidência") |
| `nomenclatura_funcionario` | VARCHAR | Label para colaborador (default: "Colaborador") |
| `nome_estrutura_dirigentes` | VARCHAR | Nome do comitê/grupo de dirigentes |
| `habilita_sgf` | INT | 0=SGF desabilitado, 1=habilitado |
| `a_vencer` | INT | Dias para considerar tarefa "a vencer" |
| `expira_sessao` | INT | Horas de inatividade para expirar sessão |
| `qtd_niveis_gerenciais` | INT | Quantos níveis estão ativos (1-4) |
| `email_financeiro` | VARCHAR | Email para notificações financeiras |

### Hierarquia Organizacional
```
estrutura_gerencial_4 (cargo=4)
    ├── estrutura_gerencial_4_id PK
    ├── sigla
    └── descricao

diretoria (cargo=3)
    ├── diretoria_id PK
    ├── sigla
    ├── descricao
    └── estrutura_gerencial_4_id FK

coordenacao (cargo=2)
    ├── coordenacao_id PK
    ├── sigla
    ├── descricao
    └── diretoria_id FK

divisao (cargo=1 responsável / cargo=0 lotado)
    ├── divisao_id PK
    ├── sigla
    ├── descricao
    └── coordenacao_id FK
```

---

## Índices Importantes

```sql
-- Busca fulltext (MATCH ... AGAINST)
ALTER TABLE demanda ADD FULLTEXT(descricao, resumo, nup);
ALTER TABLE tarefa ADD FULLTEXT(descricao);
ALTER TABLE usuario ADD FULLTEXT(nome, login);
ALTER TABLE tarefa_providencia ADD FULLTEXT(descricao);

-- Busca de notificações não lidas por usuário
INDEX idx_usuario_lida ON notificacoes(usuario_id, lida);

-- Busca de token por usuário
INDEX idx_usuario ON push_tokens(usuario_id);
UNIQUE KEY unique_token ON push_tokens(token);
```

---

## Relacionamentos Principais

```
demanda (projeto)
  ├── demanda_recursos → usuario (equipe)
  ├── tarefa → usuario (responsável)
  │     ├── tarefa_todo → usuario (responsável afazer)
  │     ├── tarefa_providencia (histórico execução)
  │     ├── tarefa_historico (log de status)
  │     ├── tarefa_anexo (arquivos no GCS)
  │     └── tarefa_link (URLs externas)
  ├── demanda_nota (comentários)
  ├── demanda_anexo (arquivos do projeto)
  ├── demanda_link (links do projeto)
  └── demanda_custo
        └── autoriza_custo (aprovações)

tarefarapida (demanda rápida)
  ├── usuario (criador)
  ├── usuario (destinatário)
  ├── tarefarapida_providencia
  ├── tarefarapida_anexo
  └── tarefarapida_link
```
