# Documentação: Campos Específicos por Tipo de Campanha

## 📋 Resumo

Com os 7 novos tipos de campanha padrão Maktubia Loyalty, foram adicionados campos específicos no banco de dados para gerenciar as funcionalidades de cada tipo.

## 🗄️ Campos Adicionados no Banco de Dados

### 1️⃣ RewardType_Auto (Oferta Automática)
- `auto_points_amount` (INTEGER) - Quantidade de pontos a dar automaticamente
- `auto_points_condition` (TEXT) - Condição para receber (ex: "após primeira compra", "ao aderir")

**Exemplo de uso:**
```json
{
  "type": "RewardType_Auto",
  "auto_points_amount": 1000,
  "auto_points_condition": "Ao aderir à campanha"
}
```

### 2️⃣ RewardType_Draw (Sorteio)
- `draw_participation_condition` (TEXT) - Condição para participar
- `draw_min_spend` (NUMERIC) - Valor mínimo de compra para participar
- `draw_chances_per_purchase` (INTEGER) - Número de chances por compra (default: 1)
- `draw_prize_description` (TEXT) - Descrição do prémio
- `draw_date` (TIMESTAMP) - Data do sorteio
- `draw_winners_count` (INTEGER) - Número de vencedores (default: 1)

**Exemplo de uso:**
```json
{
  "type": "RewardType_Draw",
  "draw_min_spend": 500,
  "draw_chances_per_purchase": 1,
  "draw_prize_description": "Jantar grátis",
  "draw_date": "2025-11-20T18:00:00Z",
  "draw_winners_count": 3
}
```

### 3️⃣ RewardType_Exchange (Troca)
- `exchange_min_points_required` (INTEGER) - Pontos mínimos necessários
- **Nota:** Usa também os campos existentes:
  - `reward_points_cost` - Custo em pontos
  - `reward_description` - Descrição da recompensa
  - `reward_value_mt` - Valor em MZN
  - `reward_stock` - Estoque disponível

**Exemplo de uso:**
```json
{
  "type": "RewardType_Exchange",
  "exchange_min_points_required": 1000,
  "reward_points_cost": 1000,
  "reward_description": "Sobremesa grátis",
  "reward_stock": 50
}
```

### 4️⃣ RewardType_Quiz (Questões)
- `quiz_questions` (JSONB) - Array de perguntas e respostas
- `quiz_points_per_correct` (INTEGER) - Pontos por resposta correta (default: 10)
- `quiz_max_attempts` (INTEGER) - Número máximo de tentativas (default: 3)
- `quiz_time_limit_seconds` (INTEGER) - Tempo limite por pergunta (opcional)

**Estrutura de `quiz_questions`:**
```json
[
  {
    "question": "Qual é a capital de Moçambique?",
    "options": ["Maputo", "Beira", "Nampula", "Quelimane"],
    "correct_answer": 0,
    "points": 10
  },
  {
    "question": "Quantos pontos ganha por cada 100 MZN?",
    "options": ["10", "100", "1000", "1"],
    "correct_answer": 0,
    "points": 10
  }
]
```

**Exemplo de uso:**
```json
{
  "type": "RewardType_Quiz",
  "quiz_questions": [...],
  "quiz_points_per_correct": 10,
  "quiz_max_attempts": 3,
  "quiz_time_limit_seconds": 30
}
```

### 5️⃣ RewardType_Referral (Indicação)
- `referral_min_referrals` (INTEGER) - Número mínimo de indicações (default: 1)
- `referral_points_per_referral` (INTEGER) - Pontos por cada indicação (default: 1000)
- `referral_bonus_points` (INTEGER) - Bônus adicional ao completar meta
- `referral_requires_first_purchase` (BOOLEAN) - Se requer primeira compra do indicado (default: true)
- `referral_code` (VARCHAR) - Código único de referência (opcional, indexado)

**Exemplo de uso:**
```json
{
  "type": "RewardType_Referral",
  "referral_min_referrals": 3,
  "referral_points_per_referral": 1000,
  "referral_bonus_points": 2000,
  "referral_requires_first_purchase": true,
  "referral_code": "MIMOS2025"
}
```

### 6️⃣ RewardType_Challenge (Desafio)
- `challenge_objective` (TEXT) - Objetivo do desafio
- `challenge_target_value` (INTEGER) - Valor alvo (ex: número de visitas, valor gasto)
- `challenge_target_type` (VARCHAR) - Tipo de alvo: 'visits', 'spend', 'purchases', 'points'
- `challenge_reward_points` (INTEGER) - Pontos ao completar
- `challenge_bonus_reward` (TEXT) - Recompensa bônus
- `challenge_progress_tracking` (BOOLEAN) - Se deve rastrear progresso (default: true)

**Exemplo de uso:**
```json
{
  "type": "RewardType_Challenge",
  "challenge_objective": "Fazer mais almoços durante a semana",
  "challenge_target_value": 5,
  "challenge_target_type": "visits",
  "challenge_reward_points": 3000,
  "challenge_bonus_reward": "Jantar especial",
  "challenge_progress_tracking": true
}
```

### 7️⃣ RewardType_Party (Votação)
- `party_voting_options` (JSONB) - Opções de voto
- `party_points_per_vote` (INTEGER) - Pontos por participar na votação (default: 10)
- `party_winner_reward` (TEXT) - Recompensa para mais votados
- `party_voting_deadline` (TIMESTAMP) - Prazo para votar
- `party_results_date` (TIMESTAMP) - Data de divulgação dos resultados

**Estrutura de `party_voting_options`:**
```json
[
  {
    "id": "option1",
    "label": "Melhor Prato do Dia",
    "description": "Prato mais saboroso do dia"
  },
  {
    "id": "option2",
    "label": "Melhor Atendimento",
    "description": "Funcionário mais atencioso"
  }
]
```

**Exemplo de uso:**
```json
{
  "type": "RewardType_Party",
  "party_voting_options": [...],
  "party_points_per_vote": 10,
  "party_winner_reward": "Tratamento premium gratuito",
  "party_voting_deadline": "2025-11-15T23:59:59Z",
  "party_results_date": "2025-11-16T12:00:00Z"
}
```

## 🔧 Campos Genéricos (JSONB)

Para flexibilidade adicional, foram adicionados 3 campos JSONB genéricos:

- `campaign_metadata` (JSONB) - Metadados flexíveis para cada tipo
- `campaign_rules` (JSONB) - Regras específicas do tipo de campanha
- `campaign_settings` (JSONB) - Configurações específicas

**Exemplo de uso:**
```json
{
  "type": "RewardType_Quiz",
  "campaign_metadata": {
    "difficulty": "medium",
    "category": "gastronomia",
    "tags": ["quiz", "educativo"]
  },
  "campaign_rules": {
    "allow_hints": false,
    "show_correct_answer": true
  },
  "campaign_settings": {
    "notifications_enabled": true,
    "reminder_days": [1, 3, 7]
  }
}
```

## 📊 Índices Criados

Para melhor performance, foram criados os seguintes índices:

- `idx_campaigns_type` - Índice no campo `type`
- `idx_campaigns_draw_date` - Índice parcial em `draw_date` (WHERE draw_date IS NOT NULL)
- `idx_campaigns_party_voting_deadline` - Índice parcial em `party_voting_deadline` (WHERE party_voting_deadline IS NOT NULL)
- `idx_campaigns_referral_code` - Índice no campo `referral_code`

## 🔄 Como Usar

### Criar Campanha com Campos Específicos

**POST /api/campaigns**

```json
{
  "type": "RewardType_Quiz",
  "campaign_name": "Quiz Gastronómico Mimos",
  "sponsor_name": "Restaurante Mimos",
  "establishment_id": 321,
  "quiz_questions": [
    {
      "question": "Qual é o prato mais popular?",
      "options": ["Frango", "Peixe", "Carne", "Vegetariano"],
      "correct_answer": 0,
      "points": 10
    }
  ],
  "quiz_points_per_correct": 10,
  "quiz_max_attempts": 3,
  "valid_from": "2025-11-10T00:00:00Z",
  "valid_until": "2025-11-20T23:59:59Z",
  "status": "Activo"
}
```

### Resposta da API

Todos os campos específicos por tipo são retornados na resposta:

```json
{
  "success": true,
  "data": {
    "id": "...",
    "type": "RewardType_Quiz",
    "typeLabel": "Questões",
    "typeDescription": "Responde às perguntas no app e ganha pontos por cada resposta certa",
    "quizQuestions": [...],
    "quizPointsPerCorrect": 10,
    "quizMaxAttempts": 3,
    "quizTimeLimitSeconds": 30,
    ...
  }
}
```

## ⚠️ Notas Importantes

1. **Campos Opcionais:** Todos os campos específicos por tipo são opcionais, exceto o campo `type` que é obrigatório.

2. **Validação Dinâmica:** O sistema valida dinamicamente se os campos existem no banco antes de tentar inserir/atualizar.

3. **Compatibilidade:** Campanhas antigas sem esses campos continuarão funcionando normalmente.

4. **JSONB vs TEXT:** Campos como `quiz_questions` e `party_voting_options` são armazenados como JSONB no PostgreSQL, mas podem ser enviados como JSON string ou objeto no request.

5. **Valores Padrão:** Alguns campos têm valores padrão (ex: `draw_chances_per_purchase = 1`, `quiz_points_per_correct = 10`).

## 🔍 Script de Migração

O script `add-campaign-type-specific-fields.js` foi executado com sucesso e adicionou todos os campos necessários.

Para executar novamente (se necessário):
```bash
node add-campaign-type-specific-fields.js
```

