# Cupones de descuento (registro + Mercado Pago)

Base URL: **`/api`**.

---

## Conceptos

| Concepto | Descripción |
|----------|-------------|
| **Cupón** | Código único, `discount_percent`, `months`, `max_total_uses`, `max_distinct_users`, vigencia opcional. |
| **Validación pública** | Solo comprueba que el cupón exista y esté activo/vigente. **No** reserva cupo. |
| **Registro con cupón** | Se valida cupo (`uses_count`, usuarios distintos, si el usuario ya canjeó). Si no hay cupo: respuesta con `cupon_used: true`. Si hay: `cupon_used: false` y se cobra con descuento. |
| **Canje** | Tabla `discount_coupon_redemptions` + incremento de `uses_count` al confirmar pago (webhook MP o efectivo en `register`). |

**`payments`**: `discount_coupon_id`, `original_amount`, `discount_percent_applied` cuando el canje se registra.

**Metadata Mercado Pago** (pago con tarjeta en registro): `discount_coupon_id` (string, id del cupón).

---

## Admin — ABM (`JwtAdminMiddleware`)

| Método | Ruta |
|--------|------|
| GET | `/api/admin/discount-coupon` |
| GET | `/api/admin/discount-coupon/{id}` |
| POST | `/api/admin/discount-coupon` |
| PUT | `/api/admin/discount-coupon/{id}` |
| DELETE | `/api/admin/discount-coupon/{id}` |

Campos: `code`, `discount_percent`, `months`, `max_total_uses`, `max_distinct_users`, `is_active`, `valid_from`, `valid_to` (ver validaciones en `DiscountCouponController`).

---

## Público — Solo existencia (`sin JWT`)

```http
POST /api/register/coupon-verify
Content-Type: application/json
```

**Body:** `{ "code": "..." }` (obligatorio).

**200:** `data.exists` true/false; si existe, `code`, `discount_percent`, `months`.

**400:** error de validación.

No reserva cupo ni calcula cobro en el servidor (más allá de devolver datos del cupón si existe).

---

## Registro

`POST /api/register` — campo opcional **`coupon_code`**.

- Si el cupón no aplica o **no hay cupo**: **400**, `status: false`, **`cupon_used: true`**, `message`.
- Si hay cupo y el registro + pago OK: en la respuesta exitosa, **`cupon_used: false`** (solo cuando enviaste `coupon_code`).

---

## Webhook Mercado Pago

Con pago **`approved`**, si `metadata.discount_coupon_id` está presente y el pago aún no tiene `discount_coupon_id`, se intenta registrar el canje (idempotente por id de pago de MP). Si en ese momento no hay cupo, no se actualiza el pago con datos de cupón.

---

## Migraciones

Orden al correr `php artisan migrate`:

1. `2026_05_09_000001_create_discount_coupons_table`
2. `2026_05_09_000002_create_discount_coupon_redemptions_table`
3. `2026_05_09_000003_add_discount_coupon_columns_to_payments_table`
