# 📱 Scan de QR Code de Campanhas - Guia Completo

## 📋 Visão Geral

Quando um cliente escaneia o QR code de uma campanha, o sistema processa automaticamente a ação apropriada baseada no tipo de campanha. Cada tipo de campanha tem um comportamento específico.

---

## 🔗 Endpoint

**POST** `/api/campaigns/scan`

**Autenticação:** Requerida (Bearer Token)

**Body:**
```json
{
  "qrCode": "MAKTUBIA_CAMP_C11A82E6_B2558ED1"
}
```

**Resposta de Sucesso:**
```json
{
  "success": true,
  "data": {
    "campaign": { /* dados da campanha */ },
    "participation": {
      "message": "Você aderiu à campanha e ganhou 100 pontos!",
      "success": true,
      "pointsEarned": 100,
      "participation": {
        "campaignId": "c11a82e6-53a2-45bd-9673-0d8c795346c5",
        "userId": 18,
        "participatedAt": "2025-11-10T15:00:00.000Z",
        "status": "active"
      }
    }
  }
}
```

---

## 🎯 Comportamento por Tipo de Campanha

### 1️⃣ **RewardType_Auto** (Oferta Automática)

**O que acontece:**
- ✅ Usuário adere automaticamente à campanha
- ✅ Recebe pontos automaticamente (configurado em `auto_points_amount` ou `accumulation_rate`)
- ✅ Pontos são adicionados à carteira imediatamente
- ✅ Registro de participação é criado

**Validações:**
- ❌ Se já participou, retorna mensagem informando
- ❌ Se plafond global (`total_points_limit`) foi atingido, não adiciona pontos
- ❌ Se campanha não possui pontos configurados, retorna erro

**Exemplo de Resposta:**
```json
{
  "message": "Você aderiu à campanha e ganhou 100 pontos!",
  "success": true,
  "pointsEarned": 100
}
```

---

### 2️⃣ **RewardType_Draw** (Sorteio)

**O que acontece:**
- ✅ Usuário participa no sorteio
- ✅ Registro de participação é criado
- ⚠️ **NÃO** recebe pontos imediatamente (pontos são dados apenas se ganhar o sorteio)

**Validações:**
- ❌ Se já está participando, retorna mensagem informando
- ❌ Se há `draw_min_spend` configurado, verifica se usuário tem compras confirmadas acima desse valor
- ❌ Se não tem compras suficientes, retorna erro pedindo para fazer compra primeiro

**Exemplo de Resposta:**
```json
{
  "message": "Você está participando no sorteio! Boa sorte!",
  "success": true,
  "participation": {
    "drawDate": "2025-11-20T00:00:00.000Z",
    "prizeDescription": "Prêmio especial"
  }
}
```

---

### 3️⃣ **RewardType_Exchange** (Troca)

**O que acontece:**
- ✅ Usuário troca pontos por recompensa
- ✅ Pontos são debitados da carteira
- ✅ Recompensa é resgatada
- ✅ Estoque é atualizado (se configurado)

**Validações:**
- ❌ Se não tem pontos suficientes, retorna erro com quantidade necessária
- ❌ Se estoque (`reward_stock`) está esgotado, retorna erro
- ❌ Se já resgatou, retorna mensagem informando

**Exemplo de Resposta:**
```json
{
  "message": "Você resgatou a recompensa por 500 pontos!",
  "success": true,
  "pointsSpent": 500,
  "rewardDescription": "Sobremesa grátis"
}
```

---

### 4️⃣ **RewardType_Quiz** (Questões)

**O que acontece:**
- ✅ Usuário inicia o quiz
- ✅ Registro de participação é criado com status `started`
- ⚠️ **NÃO** recebe pontos imediatamente (pontos são dados ao responder questões corretamente)

**Validações:**
- ❌ Se já iniciou o quiz, retorna mensagem informando e redireciona para continuar

**Exemplo de Resposta:**
```json
{
  "message": "Quiz iniciado! Responda às questões para ganhar pontos.",
  "success": true,
  "redirectTo": "/campaigns/c11a82e6-53a2-45bd-9673-0d8c795346c5/quiz/start"
}
```

**Próximos Passos:**
- Usuário deve usar o endpoint `/api/campaigns/:id/quiz/start` para ver as questões
- Usuário deve usar `/api/campaigns/:id/quiz/answer` para responder
- Pontos são dados conforme respostas corretas

---

### 5️⃣ **RewardType_Referral** (Indicação)

**O que acontece:**
- ✅ Código de indicação único é gerado para o usuário
- ✅ Registro de participação é criado com o código
- ⚠️ **NÃO** recebe pontos imediatamente (pontos são dados quando alguém usa o código)

**Validações:**
- ❌ Se já tem código de indicação, retorna o código existente

**Exemplo de Resposta:**
```json
{
  "message": "Código de indicação gerado! Compartilhe com seus amigos.",
  "success": true,
  "referralCode": "REF_C11A82E6_18_ABC123"
}
```

**Próximos Passos:**
- Usuário compartilha o código com amigos
- Quando alguém se registra usando o código, o usuário recebe pontos
- Pontos são dados conforme `referral_points_per_referral` configurado

---

### 6️⃣ **RewardType_Challenge** (Desafio)

**O que acontece:**
- ✅ Usuário aceita o desafio
- ✅ Registro de participação é criado com status `active`
- ⚠️ **NÃO** recebe pontos imediatamente (pontos são dados ao completar objetivos)

**Validações:**
- ❌ Se já aceitou o desafio, retorna mensagem informando

**Exemplo de Resposta:**
```json
{
  "message": "Desafio aceito! Complete os objetivos para ganhar pontos.",
  "success": true,
  "participation": {
    "challengeObjective": "Fazer 5 compras",
    "targetValue": 5
  }
}
```

**Próximos Passos:**
- Sistema rastreia progresso do usuário (compras, pontos, etc.)
- Quando objetivo é atingido, pontos são dados automaticamente
- Pontos são dados conforme `challenge_reward_points` configurado

---

### 7️⃣ **RewardType_Party** (Votação)

**O que acontece:**
- ✅ Usuário se registra para votar
- ✅ Registro de participação é criado com status `registered`
- ⚠️ **NÃO** recebe pontos imediatamente (pontos são dados ao votar)

**Validações:**
- ❌ Se já votou, retorna mensagem informando

**Exemplo de Resposta:**
```json
{
  "message": "Você está registrado para votar! Escolha sua opção.",
  "success": true,
  "redirectTo": "/campaigns/c11a82e6-53a2-45bd-9673-0d8c795346c5/party/vote"
}
```

**Próximos Passos:**
- Usuário deve usar endpoint específico para votar
- Pontos são dados conforme `party_points_per_vote` configurado

---

### 8️⃣ **RewardType_Voucher** (Voucher)

**O que acontece:**
- ✅ Voucher único é gerado para o usuário
- ✅ Registro de participação é criado com status `redeemed`
- ✅ Código de voucher é retornado

**Validações:**
- ❌ Se já resgatou, retorna o código de voucher existente
- ❌ Se limite de vouchers (`voucher_usage_limit`) foi atingido, retorna erro

**Exemplo de Resposta:**
```json
{
  "message": "Voucher resgatado com sucesso!",
  "success": true,
  "voucherCode": "VOUCHER_C11A82E6_18_XYZ789",
  "voucherValue": 50,
  "voucherDescription": "Desconto de 50 MT"
}
```

---

## 🗄️ Tabela `campaign_participations`

A tabela rastreia todas as participações de usuários em campanhas:

```sql
CREATE TABLE campaign_participations (
    participation_id SERIAL PRIMARY KEY,
    campaign_id VARCHAR(64) NOT NULL REFERENCES campaigns(campaign_id),
    user_id INTEGER NOT NULL REFERENCES users(user_id),
    participated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    status VARCHAR(20) DEFAULT 'active',
    points_spent INTEGER DEFAULT 0,
    points_earned INTEGER DEFAULT 0,
    referral_code VARCHAR(100),
    voucher_code VARCHAR(100),
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    UNIQUE(campaign_id, user_id)
);
```

**Status possíveis:**
- `active` - Participação ativa (Auto, Draw, Challenge, Referral)
- `started` - Iniciado mas não concluído (Quiz)
- `registered` - Registrado mas não votou (Party)
- `redeemed` - Resgatado (Exchange, Voucher)
- `completed` - Concluído
- `cancelled` - Cancelado

---

## ⚠️ Validações Globais

Todas as campanhas passam por estas validações antes de processar:

1. ✅ **Campanha existe** - QR code válido
2. ✅ **Campanha está ativa** - `active = true` e `status = 'Activo'`
3. ✅ **Campanha não expirou** - `valid_until` > agora
4. ✅ **Campanha já iniciou** - `valid_from` < agora (se configurado)
5. ✅ **Usuário autenticado** - Token válido

---

## 📝 Notas Importantes

1. **QR Code de Campanha vs Estabelecimento:**
   - QR code de campanha: `MAKTUBIA_CAMP_...` → Usa endpoint `/api/campaigns/scan`
   - QR code de estabelecimento: `MAKTUBIA_LOJA_...` → Usa endpoint `/api/purchases/scan`

2. **Pontos Imediatos vs Futuros:**
   - **Pontos imediatos:** Auto (ao aderir)
   - **Pontos futuros:** Draw (se ganhar), Quiz (ao responder), Referral (quando alguém usa código), Challenge (ao completar), Party (ao votar)

3. **Participação Duplicada:**
   - Sistema previne participação duplicada usando `UNIQUE(campaign_id, user_id)`
   - Se já participou, retorna mensagem informando e dados da participação existente

4. **Criação da Tabela:**
   - Execute o script `database/create-campaign-participations-table.sql` para criar a tabela
   - Ou execute manualmente o SQL fornecido acima

---

## 🚀 Como Usar

1. **Cliente escaneia QR code da campanha** no app
2. **App envia requisição** para `/api/campaigns/scan` com o QR code
3. **Sistema processa** baseado no tipo de campanha
4. **Sistema retorna** resultado da participação
5. **App exibe** mensagem apropriada ao usuário

---

## 🔧 Troubleshooting

**Erro: "Campanha não encontrada"**
- Verifique se o QR code está correto
- Verifique se a campanha existe no banco de dados
- Verifique se o campo `qr_code` está preenchido na tabela `campaigns`

**Erro: "Tabela campaign_participations não existe"**
- Execute o script `database/create-campaign-participations-table.sql`

**Erro: "Você já participou"**
- Normal para campanhas que não permitem participação múltipla
- Verifique dados da participação existente na resposta






