# Módulo Caridade — Documentação

Gestão de entradas e saídas de bens (alimentos, higiene, roupa, brinquedos) para famílias necessitadas e instituições parceiras. Desenvolvido na branch `feature/caridade-modulo-v2`.

**Admin (gestão):** `portal.zionlisboa.pt/admin?module=caridade`  
**App — entradas (voluntários):** `/caridade-entradas.html`  
**App — registo de famílias (líderes):** `/caridade-necessitados.html`

---

## Sumário

1. [Objetivo e âmbito](#objetivo-e-âmbito)
2. [Ficheiros do projeto](#ficheiros-do-projeto)
3. [Permissões e acesso](#permissões-e-acesso)
4. [Interface admin — abas](#interface-admin--abas)
5. [Regras de negócio](#regras-de-negócio)
6. [Indicadores e KPIs](#indicadores-e-kpis)
7. [Formulário público](#formulário-público)
8. [Email automático (cabaz)](#email-automático-cabaz)
9. [Base de dados](#base-de-dados)
10. [RPCs (Supabase)](#rpcs-supabase)
11. [Migrações SQL](#migrações-sql)
12. [Checklist de testes](#checklist-de-testes)
13. [Roadmap (não implementado)](#roadmap-não-implementado)

---

## Objetivo e âmbito

O módulo substitui o MVP standalone (`20260522*`–`20260526*`) por um **schema v2** integrado no admin Zion, cobrindo:

| Fase | Conteúdo | Estado |
|------|----------|--------|
| **1** | Entradas (sacos + artigos), saídas, stats | ✅ |
| **2** | Instituições, necessitados, saídas família/instituição | ✅ |
| **2+** | Formulário público, lookup, apoio 3 meses, KPIs | ✅ |
| **2++** | Sacos numerados, cabazes/estoque, catálogo de subtipos, aba Cadastros | ✅ |
| **3** | Termo assinatura digital instituições, app famílias | 🔜 Futuro |

---

## Ficheiros do projeto

| Ficheiro | Função |
|----------|--------|
| `modules/caridade.html` | Módulo admin — gestão completa (prefixo `cd_`, init `cd_init`) |
| `caridade-entradas.html` | App — registo de entradas (sacos e artigos) pela equipa social |
| `caridade-necessitados.html` | App — líderes registam famílias necessitadas |
| `api/caridade/cabaz-disponivel.js` | Vercel function — email “cabaz disponível” |
| `api/auth/email-templates.js` | Template `emailCabazCaridade()` |
| `admin.html` | Registo no nav, `reInitMap`, permissões, `herdarPermCaridade()` |
| `supabase/migrations/20260608*.sql` … `20260610200000_*.sql` | Schema e evoluções |
| `supabase/migrations/README.md` | Ordem de aplicação das migrações |
| `docs/schema-data.json` + `docs/schema.html` | Schema visual (referência geral; Caridade: `node scripts/merge-caridade-schema.mjs`) |
| `scripts/caridade-schema-tables.json` | Definição das 9 tabelas Caridade v2+ para o schema |
| `scripts/merge-caridade-schema.mjs` | Atualiza `schema-data.json` após evoluções do módulo |

---

## Permissões e acesso

Colunas em `usuarios` (migração `20260610120000`):

- `ver_caridade`, `criar_caridade`, `editar_caridade`, `eliminar_caridade`

**Herança automática:** utilizadores com `ver_voluntarios = true` recebem acesso total a Caridade (mesma equipa social). Implementado em SQL (UPDATE inicial) e em runtime via `herdarPermCaridade()` em `admin.html`.

No módulo: `perm('caridade', 'ver'|'criar'|'editar'|'eliminar')`.

---

## Interface admin — abas

A navegação principal tem **três secções**:

| Aba | Conteúdo |
|-----|----------|
| **Operação** | Entradas, saídas, stats mensais, export CSV |
| **KPIs** | Gráficos e filtros analíticos |
| **Cadastros** | Instituições, Necessitados, Cabazes (modelos), Subtipos |
| **Estoque** | Stock por artigo (entradas − saídas cabaz) |

### Operação

Dois sub-painéis: **Entradas** e **Saídas**.

**Stats no topo**  
Quatro cartões: Entradas kg, Saídas kg, Saldo kg, Unidades (artigos). Ver [Indicadores e KPIs](#indicadores-e-kpis).

#### Entradas — modo saco (lote)

- **Numeração automática** do saco (`nº 1`, `nº 2`, …) — calculada a partir dos lotes existentes.
- Peso obrigatório (kg).
- **Categoria do saco:** Alimento, Higiene, Roupa ou Brinquedo (pills — não usa mulher/homem/etc.).
- Campanha conforme categoria: **Caridade** (alimento) ou **Zion Em Ação** (higiene, roupa, brinquedo).

#### Entradas — modo artigo

- **Ligação ao saco:** cada artigo pertence a um lote (select dos sacos registados). O **tipo de artigo** é pré-selecionado pela categoria do saco escolhido.
- Tipos: alimento, higiene, roupa, brinquedo.
- **Subtipos:** pills clicáveis vindos do [catálogo](#subtipos) (`caridade_artigo_subtipos`); fallback local se a migração ainda não foi aplicada.
- **Alimento:** subtipo + quantidade + peso (atalhos 2 kg, 5 kg, Outro). Campanha Caridade.
- **Higiene / brinquedo:** subtipo (ou nome livre) + quantidade. Campanha Zion Em Ação.
- **Roupa:** subtipo, faixa de tamanho, tamanho, categoria destino (mulher/homem/criança/bebé).
- **Brinquedo:** subtipo (ou nome) + quantidade + público (menino/menina/ambos).

#### Saídas

- Beneficiário: **Família** ou **Instituição**.
- **Modo de saída:**
  - **Peso (kg)** — legado: peso + categoria de destino.
  - **Cabaz (itens)** — escolhe modelo de cabaz, monta lista editável (`caridade_montar_cabaz`), grava linhas em `caridade_saida_itens` e atualiza stock.
- Família: necessitado ativo ou texto livre; se email conhecido → email automático de cabaz (peso estimado no modo cabaz).
- Instituição: seleção de instituição ativa.

Listas recentes (até 100 entradas conforme modo), export CSV, eliminar (se permissão).

### KPIs

Painel analítico com filtros:

| Filtro | Opções |
|--------|--------|
| Período | Este mês, Mês anterior, Últimos 3 meses, Personalizado (datas) |
| Categoria | Todas ou uma das 7 categorias |
| Tipo de item | Todos, saco, alimento, higiene, roupa, brinquedo |

**Gráficos (SVG, sem dependências externas):**

- Entradas vs Saídas (kg)  
- Unidades vs Entregas (contagem de saídas)  
- Entradas por categoria (kg)  
- Saídas por categoria (kg)  
- Entradas por tipo de item (unidades)  
- Evolução diária (kg entradas/saídas)

Resumo numérico do período filtrado acima dos gráficos.

### Cadastros

Sub-abas dentro de **Cadastros** (a última sub-aba visitada é memorizada na sessão).

#### Instituições

CRUD simplificado: nome, morada, contacto, email. Ativar/desativar.  
Seed: Exército de Salvação, Santa Casa da Misericórdia de Loures.

#### Necessitados

Famílias apoiadas (membros ou não): nome, contactos, morada, link, ministério, estado, observações.

- **Formulário admin colapsado** por defeito.  
- **Lookup automático** ao digitar nome/email/telefone (`caridade_pesquisar_pessoa`) — cruza necessitados existentes e membros.  
- **Apoio máximo 3 meses** por família ativa; badge com dias restantes; desativação automática ao carregar referências (`caridade_desativar_apoio_expirado`).  
- Estados: `pendente` (formulário público), `ativo`, `inativo`. Validar pendente → inicia contagem dos 3 meses.  
- Link público copiável para `/caridade-necessitados.html`.

#### Cabazes

Gestão de **modelos de cabaz** e **stock por artigo**.

| Sub-painel | Função |
|------------|--------|
| **Modelos** | CRUD de modelos; itens por tipo/subtipo; seed «Cabaz família padrão»; **Novo modelo** via modal (não `prompt`) |
| **Estoque** | RPC `caridade_estoque()` — entradas modo artigo menos saídas por cabaz |

Na **Operação → Saídas**, modo **Cabaz (itens)** usa o modelo para pré-preencher a lista (quantidades ajustadas ao stock disponível).

#### Subtipos

Catálogo configurável em `caridade_artigo_subtipos`:

- Filtrar por tipo de artigo (alimento, higiene, roupa, brinquedo).
- Adicionar subtipo (nome visível + código opcional, gerado automaticamente).
- Ativar/desativar ou eliminar entradas do catálogo.

As opções ativas aparecem como **pills** nos formulários de entrada por artigo e nos itens de cabaz. Seed inicial inclui subtipos existentes (ex.: Descarte em alimentos, pasta de dentes em higiene).

---

## Regras de negócio

### Categorias de destino (artigos, saídas peso)

`mulher`, `homem`, `crianca`, `bebe`, `cama`, `alimentos`, `descarte`

### Categorias de saco (lote)

`alimento`, `higiene`, `roupa`, `brinquedo` — usadas no modo saco e para derivar o tipo no modo artigo.

### Campanhas

| Tipo de entrada | Campanha |
|-----------------|----------|
| Saco / alimento artigo | Caridade |
| Higiene, roupa, brinquedo | Zion Em Ação |

### Cálculo de peso (entradas no resumo)

Contam para **kg de entradas**:

- Todos os **sacos** (modo `saco`)  
- Artigos **alimento** com peso  

Não entram no kg: higiene, roupa, brinquedo (contam só em **unidades**).

| Tipo de entrada | Campanha |
|-----------------|----------|
| Saco alimento / artigo alimento | Caridade |
| Saco ou artigo higiene, roupa, brinquedo | Zion Em Ação |

### Stock e cabaz

- **Stock** (`caridade_estoque`): só entradas **modo artigo**; sacos em kg não entram.
- **Chave de item:** tipo + subtipo(s) + nome — função `caridade_item_chave`.
- **Saída cabaz:** grava cabeçalho em `caridade_saidas` (`modo_saida = 'cabaz'`) e linhas em `caridade_saida_itens`.
- Migração `20260610200000` relaxa CHECKs fixos de subtipo — valores válidos passam a vir do catálogo.

### Apoio à família (3 meses)

- Coluna `apoio_inicio_em` — preenchida ao passar para `ativo`.  
- Após 3 meses, RPC `caridade_desativar_apoio_expirado` marca `inativo`.  
- Chamada automaticamente ao carregar referências no admin.

### Formulário público vs admin

| Origem | Estado inicial |
|--------|----------------|
| Líder (página pública) | `pendente` — aguarda validação |
| Equipa Caridade (admin) | Conforme seleção (normalmente `ativo`) |

Contexto público: **Link** ou **Ministério** (lista plana de `ministerios`). Áreas executivas existem na BD mas o formulário público atual **não** usa o seletor geográfico Loures/Odivelas/etc.

---

## Indicadores e KPIs

### Stats do topo (Operação)

| Indicador | Significado | Período |
|-----------|-------------|---------|
| Entradas (kg) | Sacos + alimentos com peso | **Mês corrente** |
| Saídas (kg) | Soma de peso das saídas | **Mês corrente** |
| Saldo (kg) | Entradas − Saídas | **Mês corrente** |
| Unidades | Soma de `quantidade` em entradas modo artigo | **Mês corrente** |

- Timezone: **`Europe/Lisbon`**.  
- **Reinício automático** no dia 1 de cada mês (sem job externo — filtro por `criado_em` no RPC).  
- RPC: `caridade_resumo()` (atualizado na migração KPIs; inclui também `saidas_entregas` para uso futuro).

### Aba KPIs

RPC: `caridade_kpis(p_data_inicio, p_data_fim, p_categoria, p_tipo_artigo)` → JSON com totais, breakdowns e série diária.

Fallback no browser se o RPC não existir (filtra arrays locais).

---

## Formulário público

**URL:** `https://portal.zionlisboa.pt/caridade-necessitados.html`

Campos: dados da família, contexto (link ou ministério), quem regista (nome + contacto).

RPC: `caridade_registar_necessitado_publico(...)` → cria registo `pendente` com `registado_por_nome` / `registado_por_contacto`.

Autenticação: anon key Supabase (sem login Zion); RLS permissivo igual ao MVP.

---

## Email automático (cabaz)

**Trigger:** ao registar saída para **família** com email conhecido (necessitado selecionado).

**Endpoint:** `POST /api/caridade/cabaz-disponivel`

```json
{
  "saida_id": "uuid",
  "email": "familia@example.com",
  "nome": "Nome Família",
  "peso_kg": 12.5,
  "categoria": "alimentos"
}
```

Atualiza `caridade_saidas.email_enviado_em` após envio. Requer variáveis Vercel: `SUPABASE_URL`, `SUPABASE_SERVICE_KEY`, `GMAIL_USER`, `GMAIL_APP_PASSWORD`.

---

## Base de dados

### Tabelas principais

| Tabela | Descrição |
|--------|-----------|
| `caridade_entradas` | Sacos e artigos recebidos |
| `caridade_saidas` | Entregas a famílias ou instituições |
| `caridade_saida_itens` | Linhas de saída por cabaz (modo item a item) |
| `caridade_instituicoes` | Parceiros institucionais |
| `caridade_necessitados` | Famílias apoiadas |
| `caridade_cabaz_modelos` | Modelos de cabaz (cesta padrão) |
| `caridade_cabaz_modelo_itens` | Itens de cada modelo |
| `caridade_artigo_subtipos` | Catálogo configurável de subtipos por tipo |
| `caridade_areas_executivas` | Lista geográfica (seed; uso limitado na UI atual) |

### Campos relevantes — entradas

- `modo`: `saco` | `artigo`  
- `tipo_artigo`, `quantidade`, `peso_kg`, `categoria`, `campanha`, `saco` (referência ao lote, ex. `nº 3`)  
- Subtipos: `subtipo_alimento`, `subtipo_roupa`, `subtipo_higiene`, `subtipo_brinquedo`, `faixa_tamanho`, `tamanho_roupa`, `publico_brinquedo`, `nome_item`

### Campos relevantes — saídas

- `tipo_beneficiario`: `familia` | `instituicao`  
- `modo_saida`: `simples` (peso kg) | `cabaz` (itens)  
- `cabaz_modelo_id` — modelo usado na saída por cabaz  
- `necessitado_id`, `instituicao_id`, `familia`, `peso_kg`, `categoria`  
- Futuro Fase 3: `token_assinatura`, `assinado_em`, `documento_url`

### Campos relevantes — saída itens

- `saida_id`, `tipo_artigo`, subtipos, `nome_item`, `quantidade`, `peso_kg` (opcional)

### Campos relevantes — subtipos (catálogo)

- `tipo_artigo`, `codigo` (slug `a-z0-9_`), `label`, `ativo`, `ordem`

### Campos relevantes — necessitados

- `estado`, `membro_id`, `link_id`, `ministerio_id`  
- `apoio_inicio_em`, `registado_por_nome`, `registado_por_contacto`

### RLS

Políticas abertas `anon` + `authenticated` (mesmo padrão do MVP). Auth real continua a ser ZionAuth no admin; Supabase Auth não é usado.

---

## RPCs (Supabase)

| Função | Uso |
|--------|-----|
| `caridade_resumo()` | Stats mensais no topo da Operação |
| `caridade_kpis(...)` | Gráficos e resumo filtrado na aba KPIs |
| `caridade_pesquisar_pessoa(p_q)` | Autocomplete admin (necessitados + membros) |
| `caridade_registar_necessitado_publico(...)` | Submissão do formulário público |
| `caridade_desativar_apoio_expirado()` | Desativa famílias com apoio > 3 meses |
| `caridade_estoque()` | Tabela de stock por artigo (Cadastros → Cabazes → Estoque) |
| `caridade_montar_cabaz(p_modelo_id)` | Lista editável para saída por cabaz |
| `caridade_item_chave(...)` | Chave lógica tipo+subtipo+nome (interno) |

---

## Migrações SQL

**Ordem obrigatória** (Supabase SQL Editor — projeto Dev Zion):

1. `20260608120000_caridade_v2_schema.sql` — schema base (**substitui** MVP `20260522*`–`20260526*`)  
2. `20260610120000_usuarios_caridade_perms.sql`  
3. `20260610130000_caridade_necessitados_publico.sql`  
4. `20260610140000_caridade_pesquisar_pessoa.sql`  
5. `20260610150000_caridade_apoio_3_meses.sql`  
6. `20260610160000_caridade_kpis.sql` — stats mensais + KPIs  
7. `20260610170000_caridade_saco_categorias.sql` — categorias de saco (alimento, higiene, roupa, brinquedo)  
8. `20260610180000_caridade_subtipo_descarte.sql` — subtipo alimento «descarte» (legado; incluído no seed do catálogo)  
9. `20260610190000_caridade_cabaz_estoque.sql` — modelos de cabaz, stock, saída por itens  
10. `20260610200000_caridade_subtipos_catalogo.sql` — tabela `caridade_artigo_subtipos` + relaxação de CHECKs  

> **Nota:** `20260610160000` faz `DROP FUNCTION caridade_resumo()` antes de recriar (nova coluna `saidas_entregas`).  
> **Nota:** `20260610200000` inclui seed dos subtipos; após aplicá-la, novos subtipos gerem-se em **Cadastros → Subtipos**.

Detalhes curtos: [`supabase/migrations/README.md`](../supabase/migrations/README.md).

---

## Checklist de testes

- [ ] Aplicar todas as migrações v2 + incrementais (até `20260610200000`)  
- [ ] Utilizador com `ver_caridade` ou `ver_voluntarios` acede ao módulo  
- [ ] Entrada saco (numeração automática, categoria alimento/higiene/roupa/brinquedo)  
- [ ] Entrada artigo ligada a saco + subtipo do catálogo  
- [ ] Stats do topo refletem **só o mês atual**  
- [ ] Saída família modo **Peso** com email → recebe cabaz  
- [ ] Saída família modo **Cabaz** — montar lista, editar qty, stock atualiza  
- [ ] Saída instituição  
- [ ] Cadastros → Instituições (ativar/desativar)  
- [ ] Cadastros → Necessitados: lookup, validar pendente, badge apoio 3 meses  
- [ ] Cadastros → Cabazes: novo modelo (modal), itens, painel Estoque  
- [ ] Cadastros → Subtipos: adicionar subtipo e ver pills na entrada  
- [ ] Formulário público → estado `pendente` → validar no admin  
- [ ] Aba KPIs: filtros e gráficos com dados reais  
- [ ] Export CSV entradas/saídas  

---

## Roadmap (não implementado)

- Email de cabaz com **lista de itens** (modo cabaz)  
- Variantes de cabaz por perfil de família  
- Termo de entrega com assinatura digital (instituições) — campos já preparados em `caridade_saidas`  
- App ou formulário dedicado para famílias  
- Endurecer RLS quando houver política de segurança definida  
- Push/merge da branch `feature/caridade-modulo-v2` para produção  

---

## Commits na branch (referência)

| Commit | Descrição |
|--------|-----------|
| `eb7b3e7` | Módulo admin v2 (Fase 1+2), migrações, docs schema |
| `ec9e9c1` | Formulário público, permissões, herança voluntários |
| `90d1f3e` | Pesquisa automática, AE/ministério simplificado |
| `55c5f65` | Apoio 3 meses, formulário admin colapsável |
| `eae5136` | Aba KPIs e indicadores mensais |
| *(local)* | Sacos numerados, cabazes/estoque, catálogo subtipos, aba Cadastros |

---

*Última atualização: junho 2026 — equipa Devs Zion Lisboa*
