# 🛡️ Validação Rigorosa de Regras de Campanha

## 📋 Resumo

Implementado sistema de validação **rigoroso** que garante que **TODAS as regras da campanha** sejam cumpridas antes de permitir que o cliente ganhe pontos. Os pontos só são creditados automaticamente quando a compra é aprovada.

---

## ✅ Regras Implementadas

### 1. **Campanha Deve Estar Ativa**
- ❌ Se `is_active = false`, a compra é **REJEITADA**
- ✅ Mensagem: "A campanha do estabelecimento não está ativa. Não é possível ganhar pontos."

### 2. **Validade da Campanha (valid_until)**
- ❌ Se a campanha expirou, a compra é **REJEITADA**
- ✅ Mensagem: "A campanha expirou em {data}. Não é possível ganhar pontos."

### 3. **Valor Mínimo de Compra (min_spend)** ⚠️ **OBRIGATÓRIO**
- ❌ Se `purchaseAmount < min_spend`, a compra é **REJEITADA**
- ✅ Mensagem: "Valor mínimo da compra é {min_spend} MZN. Valor informado: {amount} MZN. Não é possível ganhar pontos sem atingir o valor mínimo."
- 🔒 **Esta regra é verificada ANTES de criar a compra pendente**

### 4. **Número de Visitas Obrigatórias (required_visits)**
- ❌ Se o cliente não tem o número mínimo de compras confirmadas, a compra é **REJEITADA**
- ✅ Mensagem: "É necessário ter {required_visits} compra(s) confirmada(s) neste estabelecimento antes de ganhar pontos. Você tem {current_visits} compra(s) confirmada(s)."
- 🔒 **Compras pendentes NÃO contam para esta validação**
- 📊 Só conta compras com `status = 'confirmed'`

---

## 🎯 Fluxo de Validação

```
1. Cliente escaneia QR code
   ↓
2. Sistema busca estabelecimento
   ↓
3. Sistema busca campanha ativa
   ↓
4. VALIDAÇÃO: Campanha ativa?
   ├─ ❌ NÃO → ERRO (não pode ganhar pontos)
   └─ ✅ SIM → Continua
   ↓
5. VALIDAÇÃO: Campanha válida? (valid_until)
   ├─ ❌ EXPIRADA → ERRO (não pode ganhar pontos)
   └─ ✅ VÁLIDA → Continua
   ↓
6. VALIDAÇÃO: Valor mínimo atingido? (min_spend)
   ├─ ❌ NÃO → ERRO (não pode ganhar pontos)
   └─ ✅ SIM → Continua
   ↓
7. VALIDAÇÃO: Visitas obrigatórias atendidas? (required_visits)
   ├─ ❌ NÃO → ERRO (não pode ganhar pontos)
   └─ ✅ SIM → Continua
   ↓
8. TODAS AS REGRAS CUMPRIDAS ✅
   ↓
9. Sistema calcula pontos
   ↓
10. Sistema cria compra com status 'pending'
   ↓
11. Cliente vê pontos pendentes
   ↓
12. Estabelecimento aprova compra
   ↓
13. Sistema adiciona pontos AUTOMATICAMENTE ✅
```

---

## 📱 Novos Endpoints

### **Ver Pontos Pendentes**
```
GET /api/purchases/pending-points
Authorization: Bearer {token_cliente}
```

**Resposta:**
```json
{
  "success": true,
  "data": {
    "pendingPoints": 150,
    "confirmedPoints": 500,
    "balance": 0,
    "totalPoints": 650,
    "pendingPurchases": [
      {
        "purchase_id": 1,
        "purchase_code": "COMPRA_1234567890_ABC123",
        "establishment_name": "Restaurante Sabor",
        "establishment_type": "Restaurante",
        "purchase_amount": 100.50,
        "points_earned": 20,
        "purchase_date": "2024-01-15T10:30:00Z",
        "created_at": "2024-01-15T10:30:00Z"
      }
    ],
    "pendingPurchasesCount": 1
  },
  "message": "Você tem 150 pontos pendentes aguardando aprovação de 1 compra(s)."
}
```

---

## 🔄 Fluxo de Aprovação Automática

### Quando Estabelecimento Aprova Compra:

```javascript
POST /api/purchases/:id/confirm
Authorization: Bearer {token_admin/estabelecimento}
```

**O sistema automaticamente:**

1. ✅ Verifica se compra está pendente
2. ✅ Atualiza status para `confirmed`
3. ✅ **Adiciona pontos à carteira** (`UPDATE wallets SET points = points + {pontos}`)
4. ✅ **Registra no histórico** (`INSERT INTO points_history`)
5. ✅ Retorna mensagem de sucesso

**Resposta:**
```json
{
  "success": true,
  "data": {
    "purchase_id": 1,
    "purchase_code": "COMPRA_1234567890_ABC123",
    "status": "confirmed",
    "points_earned": 20,
    "confirmed_at": "2024-01-15T11:00:00Z"
  },
  "message": "Compra confirmada! 20 pontos adicionados à carteira do cliente."
}
```

---

## 🚫 Exemplos de Rejeição

### Exemplo 1: Valor Mínimo Não Atingido
```json
{
  "success": false,
  "error": "Valor mínimo da compra é 50 MZN. Valor informado: 30 MZN. Não é possível ganhar pontos sem atingir o valor mínimo."
}
```

### Exemplo 2: Visitas Obrigatórias Não Atendidas
```json
{
  "success": false,
  "error": "É necessário ter 3 compra(s) confirmada(s) neste estabelecimento antes de ganhar pontos. Você tem 1 compra(s) confirmada(s). Esta compra não conta ainda."
}
```

### Exemplo 3: Campanha Expirada
```json
{
  "success": false,
  "error": "A campanha expirou em 31/12/2023. Não é possível ganhar pontos."
}
```

### Exemplo 4: Campanha Inativa
```json
{
  "success": false,
  "error": "A campanha do estabelecimento não está ativa. Não é possível ganhar pontos."
}
```

---

## ⚙️ Implementação Técnica

### Arquivos Modificados:

1. **`controllers/purchaseController.js`**
   - ✅ Validação rigorosa de todas as regras antes de criar compra
   - ✅ Novo endpoint `getPendingPoints` para ver pontos pendentes

2. **`routes/purchaseRoutes.js`**
   - ✅ Nova rota `GET /api/purchases/pending-points`

3. **`models/PurchasesModel.js`**
   - ✅ Método `confirm` já adiciona pontos automaticamente ✅

### Validações Implementadas:

```javascript
// 1. Campanha ativa
if (campaign && !campaign.is_active) {
    return next(ErrorResponse.validation('...'));
}

// 2. Validade da campanha
if (campaign && validUntil && now > validUntilDate) {
    return next(ErrorResponse.validation('...'));
}

// 3. Valor mínimo
if (campaign && minSpend > 0 && purchaseAmountFloat < minSpend) {
    return next(ErrorResponse.validation('...'));
}

// 4. Visitas obrigatórias
if (campaign && requiredVisits > 0 && previousVisits < requiredVisits) {
    return next(ErrorResponse.validation('...'));
}
```

---

## ✅ Garantias

1. ✅ **Nenhuma compra é criada** se as regras não forem cumpridas
2. ✅ **Pontos só são calculados** se todas as regras passarem
3. ✅ **Pontos são adicionados automaticamente** quando compra é aprovada
4. ✅ **Cliente pode ver pontos pendentes** antes da aprovação
5. ✅ **Todas as validações são feitas antes** de criar a compra pendente

---

## 📊 Exemplo Completo

### Cenário: Cliente tenta comprar abaixo do mínimo

**Request:**
```bash
POST /api/purchases/scan
{
  "qrCode": "MAKTUBIA_SHOP_001",
  "purchaseAmount": 30
}
```

**Campanha:**
- `min_spend`: 50 MZN
- `conversion_rate`: 0.2
- `required_visits`: 0
- `is_active`: true

**Resposta:**
```json
{
  "success": false,
  "error": "Valor mínimo da compra é 50 MZN. Valor informado: 30 MZN. Não é possível ganhar pontos sem atingir o valor mínimo."
}
```

**Resultado:** ❌ Compra **NÃO é criada**, nenhum ponto é calculado.

---

## 🎯 Benefícios

1. ✅ **Integridade de Dados**: Apenas compras válidas são criadas
2. ✅ **Transparência**: Cliente sabe exatamente por que não ganhou pontos
3. ✅ **Automação**: Pontos creditados automaticamente na aprovação
4. ✅ **Visibilidade**: Cliente vê pontos pendentes em tempo real
5. ✅ **Consistência**: Todas as regras são validadas rigorosamente

---

## 🔒 Segurança

- ✅ Validações acontecem **ANTES** de criar a compra
- ✅ Pontos só são calculados se **TODAS** as regras passarem
- ✅ Compras inválidas **NÃO** são criadas no banco
- ✅ Histórico de pontos só registra compras válidas




