# Admin Panel - Stripe Management Quick Guide

## 🎯 Access

**URL:** `http://localhost:5173/admin`  
**Requires:** User with `admin` role

---

## 📦 Billing Plans Management

### Location

Dashboard → **"Catalogue des plans"** section

### View Plans

Les plans s'affichent automatiquement au chargement. Chaque carte affiche:

- **Nom & prix** du plan
- **Badge** "Stripe lié" ✅ ou "Stripe manquant" ⚠️
- **Statut** Actif/Masqué
- **Limites** principales (plans/mois, arrêts, IA, etc.)
- **Fonctionnalités** (jusqu'à 6 affichées)

### Edit a Plan

1. **Click "Modifier"** sur la carte du plan
2. **Edit fields:**
   - Nom
   - Description
   - Prix (montant numérique)
   - Devise (EUR, USD, etc.)
   - Facturation (Mensuel/Annuel)
   - Badge (ex: "Populaire", "Nouveau")
   - Mois offerts (promotion)
   - Mise en avant (texte d'accroche)
   - Fonctionnalités (1 par ligne)
   - Plan visible (actif/masqué)
   - Ordre d'affichage (tri)

3. **Click "Enregistrer"**

### What Happens on Save

```
Frontend → POST /api/admin/billing/plans/:id
    ↓
Backend billing.service.upsertPlan(plan, { syncStripe: true })
    ↓
Stripe API calls:
  - Create/Update Product (stripeProductId)
  - Create/Update Price (stripePriceId)
    ↓
Save to Firestore with Stripe IDs
    ↓
Frontend refreshes → Badge "Stripe lié" ✅
```

**Result:**
- ✅ Plan saved in Firestore
- ✅ Stripe Product created/updated
- ✅ Stripe Price created/updated
- ✅ IDs saved: `stripePriceId`, `stripeProductId`

### Visual Indicators

| Badge | Meaning |
|-------|---------|
| 🟢 **Stripe lié** | Plan synced with Stripe (`stripePriceId` present) |
| 🟡 **Stripe manquant** | Not yet synced (save to create Stripe product) |
| 👁️ **Actif** | Visible to users |
| 🚫 **Masqué** | Hidden (not purchasable) |

### Refresh Plans

Click **"Actualiser"** button to reload from backend.

---

## ✨ Creating New Plans

### Method 1: Via Code (Recommended)

**File:** `apps/api/src/modules/billing/billing.constants.ts`

```typescript
export function buildDefaultPlans(): SubscriptionPlan[] {
  return [
    // ... existing plans
    {
      id: 'enterprise',
      name: 'Enterprise',
      tier: 'pro',
      description: 'For large teams',
      monthlyPrice: 99.99,
      currency: 'eur',
      billingInterval: 'monthly',
      stripeProductId: null,
      stripePriceId: null,
      features: [
        'Unlimited plans',
        'Unlimited stops',
        'Priority support',
        '50 collaborators'
      ],
      limits: {
        plansPerMonth: -1,
        stopsPerPlan: -1,
        aiCallsPerMonth: -1,
        collaborators: 50,
        storageGB: 1000
      },
      highlight: 'Best for teams',
      badge: 'Enterprise',
      active: true,
      displayOrder: 4,
      createdAt: new Date().toISOString(),
      updatedAt: new Date().toISOString()
    }
  ]
}
```

**Then:**
1. Restart backend: `cd apps/api && pnpm dev`
2. Open admin panel
3. Click "Actualiser"
4. New plan appears
5. Click "Modifier" → "Enregistrer" to sync with Stripe

### Method 2: Via API (Advanced)

```bash
POST /api/admin/billing/plans
Authorization: Bearer YOUR_ADMIN_TOKEN

{
  "id": "enterprise",
  "name": "Enterprise",
  "monthlyPrice": 99.99,
  "currency": "eur",
  "billingInterval": "monthly",
  "features": ["..."],
  "limits": { ... },
  "active": true,
  "displayOrder": 4
}
```

---

## 🔄 Sync Status

### Force Re-sync

If Stripe shows wrong data:

1. Open admin panel
2. Click "Modifier" on the plan
3. **Without changing anything**, click "Enregistrer"
4. Backend will re-sync with Stripe
5. Badge changes to "Stripe lié" ✅

### Check Sync in Stripe Dashboard

1. Open https://dashboard.stripe.com/products
2. Find product by name
3. Verify:
   - Product name matches
   - Price matches
   - Currency matches
   - Recurring interval matches (monthly/yearly)

---

## 🐛 Troubleshooting

### Badge shows "Stripe manquant"

**Cause:** `stripePriceId` not set in Firestore

**Fix:**
1. Admin panel → Click "Modifier"
2. Click "Enregistrer" (no changes needed)
3. Backend syncs with Stripe
4. Badge updates to "Stripe lié" ✅

### Plan not visible to users

**Check:**
- `active` field is `true`
- Plan has `stripePriceId` (for paid plans)
- Frontend filters: `billingStore.plans` shows only active plans

**Fix:**
- Admin panel → Edit plan → Toggle "Plan visible" → Save

### Price doesn't match Stripe

**Cause:** Price changed but not synced

**Fix:**
1. Admin panel → Edit plan
2. Update price
3. Save → Creates new Stripe Price
4. Old price remains in Stripe (inactive)

**Note:** Stripe prices are immutable. Changing price creates a new `price_...` ID.

### Multiple prices for same product

**Normal behavior:** Each price change creates a new Stripe Price ID.

**To clean up:**
1. Stripe Dashboard → Products → Select product
2. Archive old prices (keep only active one)

---

## 📊 Admin Workflow Examples

### Scenario 1: Launch new plan

1. **Add to code** (`billing.constants.ts`)
2. **Restart backend**
3. **Admin panel** → "Actualiser"
4. **Edit plan** → Set badge "Nouveau" → Save
5. **Verify Stripe** → Product created ✅
6. **Test checkout** → `billingStore.checkout('new-plan-id')`

### Scenario 2: Change plan price

1. **Admin panel** → Edit plan
2. **Change price** (e.g., 9.99 → 12.99)
3. **Save** → New Stripe Price created
4. **New `stripePriceId`** saved to Firestore
5. **Users see new price** immediately

### Scenario 3: Hide plan temporarily

1. **Admin panel** → Edit plan
2. **Toggle "Plan visible"** → OFF
3. **Save**
4. **Plan hidden** from `/billing/plans` endpoint
5. **Existing subscriptions** continue normally

### Scenario 4: Add promotional badge

1. **Admin panel** → Edit plan
2. **Badge:** "50% OFF"
3. **Mois offerts:** 2
4. **Mise en avant:** "Économisez 50% sur 2 mois"
5. **Save**
6. **Badge appears** on billing page

---

## 🔒 Permissions

**Admin panel requires:**
- User authenticated (Firebase token)
- User has `admin` role in Firestore
- Check: `authStore.user.role === 'admin'`

**Backend endpoints:**
- `/api/admin/billing/*` → Requires `request.user.admin === true`
- `/api/billing/*` → Public (list plans) or authenticated (checkout)

---

## 🚀 Best Practices

1. **Always test in Stripe test mode first**
   - Use `sk_test_...` keys
   - Test checkout flow
   - Verify webhooks

2. **Keep plan IDs consistent**
   - `free`, `premium`, `pro` (lowercase)
   - Don't change IDs after users subscribe

3. **Use displayOrder for sorting**
   - Free: 0
   - Premium: 1
   - Pro: 2
   - Custom plans: 3+

4. **Document price changes**
   - Add comment in code when changing prices
   - Track in CHANGELOG.md

5. **Sync after env changes**
   - If changing `STRIPE_SECRET_KEY`, re-sync all plans

---

## 📝 Related Files

| File | Purpose |
|------|---------|
| `apps/web/src/modules/admin/components/BillingPlansAdminPanel.vue` | Admin UI |
| `apps/web/src/modules/admin/stores/adminStore.ts` | Admin state management |
| `apps/api/src/modules/billing/billing.service.ts` | Stripe sync logic |
| `apps/api/src/modules/billing/billing.constants.ts` | Default plans |
| `packages/types/src/billing.types.ts` | Type definitions |

---

## 🔗 Quick Links

- **Stripe Dashboard**: https://dashboard.stripe.com
- **Stripe Products**: https://dashboard.stripe.com/products
- **Stripe Webhooks**: https://dashboard.stripe.com/webhooks
- **Local Admin Panel**: http://localhost:5173/admin
- **API Docs**: `docs/STRIPE_SETUP.md`
